mirror of
git://nv-tegra.nvidia.com/tegra/gfx-src/nv-xconfig.git
synced 2025-12-22 09:22:53 +03:00
069ad68dd61a879f00fb30d35a10180d5951ddb0 - nvidia-xconfig-580.00/Makefile 4cc77b90af91e615a64ae04893fdffa7939db84c - nvidia-xconfig-580.00/COPYING e67b6dba2eb0dfcee7213598cd0c45b46c12fa88 - nvidia-xconfig-580.00/option_table.h 647e7896275a1113ec99352d573823a05001f57e - nvidia-xconfig-580.00/lscf.c 1e39095238886dfc6a69f7ec750e10c05a93e7d1 - nvidia-xconfig-580.00/nvidia-xconfig.1.m4 a5ad539267b73169480e7898b284823639c4db3a - nvidia-xconfig-580.00/tree.c 89c18e4a9734816026726377e96eb9ccd4fff018 - nvidia-xconfig-580.00/nvidia-xconfig.c 8ce5587db4b7482d207f347415f10c3562e3bb6d - nvidia-xconfig-580.00/options.c 0f390dff6644fa2454a96d5aa9ff5478e88b20ed - nvidia-xconfig-580.00/nvidia-cfg.h 071d03a0ec013e39290d8bf08f1a57565f8580e4 - nvidia-xconfig-580.00/nvidia-xconfig.h bfa37f78ba458f14a1865bbf3f67eb84987a7e1c - nvidia-xconfig-580.00/extract_edids.c d37da5a118e0418b267a48d05fd144611316b42c - nvidia-xconfig-580.00/gen-manpage-opts.c 41bcac41393c9a465c30c07cf1ab386647a16687 - nvidia-xconfig-580.00/util.c 9b0c02164398be2795fea7cb13c9e1b062d24bfb - nvidia-xconfig-580.00/query_gpu_info.c c946eefad99cec9366d8abbd4e45c5d138d3b7be - nvidia-xconfig-580.00/make_usable.c a45c13d9f89e79eb41b014104b01fa8b1d5029ae - nvidia-xconfig-580.00/multiple_screens.c c7b8d8ca0f7c9dcc2cdca4f8e77d1122c71892ef - nvidia-xconfig-580.00/XF86Config-parser/Read.c a9bc06f33bf525c2b08be2dc3cd64a59c4c7946d - nvidia-xconfig-580.00/XF86Config-parser/Configint.h 2022a4a3c2a1b23a67ae74f50a3849f5f3a45e4b - nvidia-xconfig-580.00/XF86Config-parser/Keyboard.c 83b0a8efd6a508db54995688ab353591bdb242a2 - nvidia-xconfig-580.00/XF86Config-parser/Flags.c e67d630ef396ab7d34524c333f3a77fc42ba8fc6 - nvidia-xconfig-580.00/XF86Config-parser/configProcs.h f3d611bdbddfa64675a0810ef81dada57e224bcd - nvidia-xconfig-580.00/XF86Config-parser/Extensions.c 5ffb2caa5077a2e6ec1c5ece807e71503fb2fbce - nvidia-xconfig-580.00/XF86Config-parser/Module.c 7344be997921dec57959691e986763ee686888d5 - nvidia-xconfig-580.00/XF86Config-parser/Device.c 33211ca0a10f50e2c87b9e8feef6c1ab381b57a1 - nvidia-xconfig-580.00/XF86Config-parser/DRI.c 953b945f3b117d6fb44f1f738af17b6380a9ec72 - nvidia-xconfig-580.00/XF86Config-parser/Monitor.c 6c210ad0eaee1db3fec48ff01746cb054b4f9aaa - nvidia-xconfig-580.00/XF86Config-parser/Video.c 4407207cf890539dc604cff5b834c994b307729a - nvidia-xconfig-580.00/XF86Config-parser/Write.c de1c758e29f217e1a99e4c076d54ac84bce98b18 - nvidia-xconfig-580.00/XF86Config-parser/Screen.c c66a0a141e25e31b568fb9df41f17d7fb9e6d3b9 - nvidia-xconfig-580.00/XF86Config-parser/xf86Parser.h 9cbc29da282aa957f28b7fc83caf1e3b19ee2a52 - nvidia-xconfig-580.00/XF86Config-parser/Vendor.c 18711ff932af2202869a30f3b32d6d7fe7811c84 - nvidia-xconfig-580.00/XF86Config-parser/Layout.c cda3a4ab05bf48ba28af35b5c4c632e968afc7fa - nvidia-xconfig-580.00/XF86Config-parser/Util.c ec19d673a6a7d1d8f855f2d32d3e8f63046c3625 - nvidia-xconfig-580.00/XF86Config-parser/Files.c ac878b26ded86a3c502a6a81fc4c4a96162afefb - nvidia-xconfig-580.00/XF86Config-parser/Merge.c 0a274c4bc54b6ae0f6d009e443bda0cb033d66b5 - nvidia-xconfig-580.00/XF86Config-parser/Pointer.c 3f2238c88d737bd329a9bca1ac4b0bcf77bb9ac2 - nvidia-xconfig-580.00/XF86Config-parser/xf86tokens.h 45ceb0129668346ae3e52d81bb6e2f97efadf9d0 - nvidia-xconfig-580.00/XF86Config-parser/Input.c 4d9b03ea3badceb6bdfdf6589e6731140ec44079 - nvidia-xconfig-580.00/XF86Config-parser/Generate.c 04efe162cf6d97882f2bb87f3712d9a65c2320f3 - nvidia-xconfig-580.00/XF86Config-parser/Scan.c 5d55b94375c2055cfa1578e4c7f34c90e63a33f7 - nvidia-xconfig-580.00/common-utils/gen-manpage-opts-helper.c 384e36102dcd08ed4c5de05b5e3b8a7cdb2e257d - nvidia-xconfig-580.00/common-utils/nvgetopt.c 6bc8be0bf82d813c3274145e689f5b10d534910c - nvidia-xconfig-580.00/common-utils/common-utils.h 8db48a58d1654ed69920366bef10f38b789a1a84 - nvidia-xconfig-580.00/common-utils/msg.c e572cac43202f6c2af1c80b9e3901215126093ed - nvidia-xconfig-580.00/common-utils/nvgetopt.h 205071eacd9a24d07fea6a512fed1e1ce97ebc3a - nvidia-xconfig-580.00/common-utils/common-utils.c 1654638c567bc7f2bd70b54d807b498ab14c1061 - nvidia-xconfig-580.00/common-utils/nvpci-utils.h 8259a24058c714629f9819cc8c830ea9b202bb27 - nvidia-xconfig-580.00/common-utils/gen-manpage-opts-helper.h 524990f5497f9bbeb3d148b5e7dc8d2267c3163d - nvidia-xconfig-580.00/common-utils/nvpci-utils.c abb5c1b445d9353f2d2840bda848cd16109710a4 - nvidia-xconfig-580.00/common-utils/msg.h Change-Id: Ib9886073c5af1500cb5b84295e9497b00ee1e54a
1492 lines
47 KiB
C
1492 lines
47 KiB
C
/*
|
|
* nvidia-xconfig: A tool for manipulating X config files,
|
|
* specifically for use by the NVIDIA Linux graphics driver.
|
|
*
|
|
* Copyright (C) 2005 NVIDIA Corporation
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms and conditions of the GNU General Public License,
|
|
* version 2, as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, see <http://www.gnu.org/licenses>.
|
|
*
|
|
*
|
|
* Generate.c
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/mman.h>
|
|
#include <fcntl.h>
|
|
|
|
|
|
#include "xf86Parser.h"
|
|
#include "Configint.h"
|
|
|
|
#define MOUSE_IDENTIFER "Mouse0"
|
|
#define KEYBOARD_IDENTIFER "Keyboard0"
|
|
|
|
#define SCREEN_IDENTIFIER "Screen%d"
|
|
#define DEVICE_IDENTIFIER "%sDevice%d"
|
|
#define MONITOR_IDENTIFIER "Monitor%d"
|
|
|
|
|
|
static int is_file(const char *filename);
|
|
|
|
static void add_font_path(GenerateOptions *gop, XConfigPtr config);
|
|
static void add_modules(GenerateOptions *gop, XConfigPtr config);
|
|
|
|
static void add_layout(GenerateOptions *gop, XConfigPtr config);
|
|
|
|
static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
|
|
char *name, char *coreKeyword);
|
|
|
|
/*
|
|
* xconfigGenerate() - generate a new XConfig from scratch
|
|
*/
|
|
|
|
XConfigPtr xconfigGenerate(GenerateOptions *gop)
|
|
{
|
|
XConfigPtr config;
|
|
|
|
config = xconfigAlloc(sizeof(XConfigRec));
|
|
|
|
/* add files, fonts, and modules */
|
|
|
|
config->files = xconfigAlloc(sizeof(XConfigFilesRec));
|
|
add_font_path(gop, config);
|
|
add_modules(gop, config);
|
|
|
|
/* add the keyboard and mouse */
|
|
|
|
xconfigAddKeyboard(gop, config);
|
|
xconfigAddMouse(gop, config);
|
|
|
|
/* add the layout */
|
|
|
|
add_layout(gop, config);
|
|
|
|
return config;
|
|
|
|
} /* xconfigGenerate() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGenerateAddScreen() - add a new screen to the config; bus
|
|
* and slot can be -1 to be ignored; boardname can be NULL to be
|
|
* ignored; count is used when building the identifier name, eg
|
|
* '"Screen%d", count'. Note that this does not append the screen to
|
|
* any layout's adjacency list.
|
|
*/
|
|
|
|
XConfigScreenPtr xconfigGenerateAddScreen(XConfigPtr config,
|
|
int bus, int domain, int slot,
|
|
char *boardname, int count,
|
|
const char *driver,
|
|
const char *vendor)
|
|
{
|
|
XConfigScreenPtr screen, s;
|
|
XConfigDevicePtr device;
|
|
XConfigMonitorPtr monitor;
|
|
|
|
monitor = xconfigAddMonitor(config, count);
|
|
device = add_device(config, bus, domain, slot, boardname, count,
|
|
driver, vendor, TRUE /* active */);
|
|
|
|
screen = xconfigAlloc(sizeof(XConfigScreenRec));
|
|
|
|
screen->identifier = xconfigAlloc(32);
|
|
snprintf(screen->identifier, 32, SCREEN_IDENTIFIER, count);
|
|
|
|
screen->device_name = xconfigStrdup(device->identifier);
|
|
screen->device = device;
|
|
|
|
screen->monitor_name = xconfigStrdup(monitor->identifier);
|
|
screen->monitor = monitor;
|
|
|
|
screen->defaultdepth = 24;
|
|
|
|
xconfigAddDisplay(&screen->displays, screen->defaultdepth);
|
|
|
|
/* append to the end of the screen list */
|
|
|
|
if (!config->screens) {
|
|
config->screens = screen;
|
|
} else {
|
|
for (s = config->screens; s->next; s = s->next);
|
|
s->next = screen;
|
|
}
|
|
|
|
return screen;
|
|
|
|
} /* xconfigGenerateAddScreen() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGenerateAssignScreenAdjacencies() - setup all the adjacency
|
|
* information for the X screens in the given layout. Nothing fancy
|
|
* here: just position all the screens horizontally, moving from left
|
|
* to right.
|
|
*/
|
|
|
|
void xconfigGenerateAssignScreenAdjacencies(XConfigLayoutPtr layout)
|
|
{
|
|
XConfigAdjacencyPtr adj, prev = NULL;
|
|
|
|
for (adj = layout->adjacencies; adj; adj = adj->next) {
|
|
|
|
if (prev) {
|
|
adj->where = CONF_ADJ_RIGHTOF;
|
|
adj->refscreen = xconfigStrdup(prev->screen_name);
|
|
} else {
|
|
adj->x = adj->y = -1;
|
|
}
|
|
|
|
/* make sure all the obsolete positioning is empty */
|
|
|
|
adj->top = NULL;
|
|
adj->top_name = NULL;
|
|
adj->bottom = NULL;
|
|
adj->bottom_name = NULL;
|
|
adj->left = NULL;
|
|
adj->left_name = NULL;
|
|
adj->right = NULL;
|
|
adj->right_name = NULL;
|
|
|
|
prev = adj;
|
|
}
|
|
|
|
} /* xconfigGenerateAssignScreenAdjacencies() */
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
|
|
|
|
/*
|
|
* is_file()
|
|
*/
|
|
|
|
static int is_file(const char *filename)
|
|
{
|
|
return (access(filename, F_OK) == 0);
|
|
|
|
} /* is_file() */
|
|
|
|
|
|
/*
|
|
* find_libdir() - attempt to find the X server library path; this is
|
|
* either
|
|
*
|
|
* `pkg-config --variable=libdir xorg-server`
|
|
*
|
|
* or
|
|
*
|
|
* [X PROJECT ROOT]/lib
|
|
*/
|
|
|
|
static char *find_libdir(GenerateOptions *gop)
|
|
{
|
|
struct stat stat_buf;
|
|
FILE *stream = NULL;
|
|
char *s, *libdir = NULL;
|
|
|
|
/*
|
|
* run the pkg-config command and read the output; if the output
|
|
* is a directory, then return that as the libdir
|
|
*/
|
|
|
|
stream = popen("pkg-config --variable=libdir xorg-server", "r");
|
|
|
|
if (stream) {
|
|
char buf[256];
|
|
|
|
buf[0] = '\0';
|
|
|
|
while (1) {
|
|
if (fgets(buf, 255, stream) == NULL) break;
|
|
|
|
if (buf[0] != '\0') {
|
|
|
|
/* truncate any newline */
|
|
|
|
s = strchr(buf, '\n');
|
|
if (s) *s = '\0';
|
|
|
|
if ((stat(buf, &stat_buf) == 0) &&
|
|
(S_ISDIR(stat_buf.st_mode))) {
|
|
|
|
libdir = xconfigStrdup(buf);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pclose(stream);
|
|
|
|
if (libdir) return libdir;
|
|
}
|
|
|
|
/* otherwise, just fallback to [X PROJECT ROOT]/lib */
|
|
|
|
return xconfigStrcat(gop->x_project_root, "/lib", NULL);
|
|
|
|
} /* find_libdir() */
|
|
|
|
|
|
|
|
/*
|
|
* add_font_path() - scan through the __font_paths[] array,
|
|
* temporarily chop off the ":unscaled" appendage, and check for the
|
|
* file "fonts.dir" in the directory. If fonts.dir exists, append the
|
|
* path to config->files->fontpath.
|
|
*/
|
|
|
|
static void add_font_path(GenerateOptions *gop, XConfigPtr config)
|
|
{
|
|
int i, ret;
|
|
char *path, *p, *orig, *fonts_dir, *libdir;
|
|
|
|
/*
|
|
* The below font path has been constructed from various examples
|
|
* and uses some suggests from the Font De-uglification HOWTO
|
|
*/
|
|
|
|
static const char *__font_paths[] = {
|
|
"LIBDIR/X11/fonts/local/",
|
|
"LIBDIR/X11/fonts/misc/:unscaled",
|
|
"LIBDIR/X11/fonts/100dpi/:unscaled",
|
|
"LIBDIR/X11/fonts/75dpi/:unscaled",
|
|
"LIBDIR/X11/fonts/misc/",
|
|
"LIBDIR/X11/fonts/Type1/",
|
|
"LIBDIR/X11/fonts/CID/",
|
|
"LIBDIR/X11/fonts/Speedo/",
|
|
"LIBDIR/X11/fonts/100dpi/",
|
|
"LIBDIR/X11/fonts/75dpi/",
|
|
"LIBDIR/X11/fonts/cyrillic/",
|
|
"LIBDIR/X11/fonts/TTF/",
|
|
"LIBDIR/X11/fonts/truetype/",
|
|
"LIBDIR/X11/fonts/TrueType/",
|
|
"LIBDIR/X11/fonts/Type1/sun/",
|
|
"LIBDIR/X11/fonts/F3bitmaps/",
|
|
"/usr/local/share/fonts/ttfonts",
|
|
"/usr/share/fonts/default/Type1",
|
|
"/usr/lib/openoffice/share/fonts/truetype",
|
|
NULL
|
|
};
|
|
|
|
/*
|
|
* if a font server is running, set the font path to that
|
|
*
|
|
* XXX should we check the port the font server is using?
|
|
*/
|
|
#if defined(NV_SUNOS)
|
|
ret = system("ps -e -o fname | grep -v grep | egrep \"^xfs$\" > /dev/null");
|
|
#elif defined(NV_BSD)
|
|
ret = system("ps -e -o comm | grep -v grep | egrep \"^xfs$\" > /dev/null");
|
|
#else
|
|
ret = system("ps -C xfs 2>&1 > /dev/null");
|
|
#endif
|
|
if (WEXITSTATUS(ret) == 0) {
|
|
config->files->fontpath = xconfigStrdup("unix/:7100");
|
|
} else {
|
|
|
|
/* get the X server libdir */
|
|
|
|
libdir = find_libdir(gop);
|
|
|
|
for (i = 0; __font_paths[i]; i++) {
|
|
path = xconfigStrdup(__font_paths[i]);
|
|
|
|
/* replace LIBDIR with libdir */
|
|
|
|
if (strncmp(path, "LIBDIR", 6) == 0) {
|
|
p = xconfigStrcat(libdir, path + 6, NULL);
|
|
free(path);
|
|
path = p;
|
|
}
|
|
|
|
/* temporarily chop off any ":unscaled" appendage */
|
|
|
|
p = strchr(path, ':');
|
|
if (p) *p = '\0';
|
|
|
|
/* skip this entry if the fonts.dir does not exist */
|
|
|
|
fonts_dir = xconfigStrcat(path, "/fonts.dir", NULL);
|
|
if (!is_file(fonts_dir)) {
|
|
/* does not exist */
|
|
free(path);
|
|
free(fonts_dir);
|
|
continue;
|
|
}
|
|
free(fonts_dir);
|
|
|
|
/* add the ":unscaled" back */
|
|
|
|
if (p) *p = ':';
|
|
|
|
/*
|
|
* either use this path as the fontpath, or append to the
|
|
* existing fontpath
|
|
*/
|
|
|
|
if (config->files->fontpath) {
|
|
orig = config->files->fontpath;
|
|
config->files->fontpath = xconfigStrcat(orig, ",", path, NULL);
|
|
free(orig);
|
|
free(path);
|
|
} else {
|
|
config->files->fontpath = path;
|
|
}
|
|
}
|
|
|
|
/* free the libdir string */
|
|
|
|
free(libdir);
|
|
}
|
|
} /* add_font_path() */
|
|
|
|
|
|
|
|
/*
|
|
* add_modules()
|
|
*/
|
|
|
|
static void add_modules(GenerateOptions *gop, XConfigPtr config)
|
|
{
|
|
XConfigLoadPtr l = NULL;
|
|
|
|
/*
|
|
* if the X server will automatically autoload GLX, then don't
|
|
* bother adding a modules section; it is difficult for
|
|
* nvidia-xconfig to know if modules like "type1" are present,
|
|
* anyway.
|
|
*/
|
|
|
|
if (gop->autoloads_glx) return;
|
|
|
|
config->modules = xconfigAlloc(sizeof(XConfigModuleRec));
|
|
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("dbe"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("extmod"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("type1"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
#if defined(NV_SUNOS)
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("IA"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("bitstream"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("xtsol"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
#else
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("freetype"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
#endif
|
|
xconfigAddNewLoadDirective(&l, xconfigStrdup("glx"),
|
|
XCONFIG_LOAD_MODULE, NULL, FALSE);
|
|
|
|
config->modules->loads = l;
|
|
|
|
} /* add_modules() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigAddMonitor() -
|
|
*
|
|
* XXX pass EDID values into this...
|
|
*/
|
|
|
|
XConfigMonitorPtr xconfigAddMonitor(XConfigPtr config, int count)
|
|
{
|
|
XConfigMonitorPtr monitor, m;
|
|
|
|
/* XXX need to query resman for the EDID */
|
|
|
|
monitor = xconfigAlloc(sizeof(XConfigMonitorRec));
|
|
|
|
monitor->identifier = xconfigAlloc(32);
|
|
snprintf(monitor->identifier, 32, MONITOR_IDENTIFIER, count);
|
|
monitor->vendor = xconfigStrdup("Unknown"); /* XXX */
|
|
monitor->modelname = xconfigStrdup("Unknown"); /* XXX */
|
|
|
|
monitor->options = NULL;
|
|
xconfigAddNewOption(&monitor->options, "DPMS", NULL);
|
|
|
|
/* append to the end of the monitor list */
|
|
|
|
if (!config->monitors) {
|
|
config->monitors = monitor;
|
|
} else {
|
|
for (m = config->monitors; m->next; m = m->next);
|
|
m->next = monitor;
|
|
}
|
|
|
|
return monitor;
|
|
|
|
} /* xconfigAddMonitor() */
|
|
|
|
|
|
|
|
/*
|
|
* add_device()
|
|
*/
|
|
|
|
XConfigDevicePtr add_device(XConfigPtr config, int bus, int domain,
|
|
int slot, char *boardname, int count,
|
|
const char *driver, const char *vendor, int active)
|
|
{
|
|
XConfigDevicePtr device, d;
|
|
|
|
device = xconfigAlloc(sizeof(XConfigDeviceRec));
|
|
|
|
device->identifier = xconfigAlloc(32);
|
|
snprintf(device->identifier, 32, DEVICE_IDENTIFIER,
|
|
active ? "" : "Inactive", count);
|
|
device->index_id = count;
|
|
device->driver = xconfigStrdup(driver);
|
|
device->vendor = xconfigStrdup(vendor);
|
|
|
|
if (bus != -1 && domain != -1 && slot != -1) {
|
|
device->busid = xconfigAlloc(32);
|
|
xconfigFormatPciBusString(device->busid, 32, domain, bus, slot, 0);
|
|
}
|
|
|
|
if (boardname) device->board = xconfigStrdup(boardname);
|
|
|
|
device->chipid = -1;
|
|
device->chiprev = -1;
|
|
device->irq = -1;
|
|
device->screen = -1;
|
|
|
|
/* append to the end of the device list */
|
|
|
|
if (!config->devices) {
|
|
config->devices = device;
|
|
} else {
|
|
for (d = config->devices; d->next; d = d->next);
|
|
d->next = device;
|
|
}
|
|
|
|
return device;
|
|
|
|
} /* add_device() */
|
|
|
|
|
|
|
|
void xconfigAddDisplay(XConfigDisplayPtr *pHead, const int depth)
|
|
{
|
|
XConfigDisplayPtr display;
|
|
|
|
display = xconfigAlloc(sizeof(XConfigDisplayRec));
|
|
display->depth = depth;
|
|
display->modes = NULL;
|
|
display->frameX0 = -1;
|
|
display->frameY0 = -1;
|
|
display->black.red = -1;
|
|
display->white.red = -1;
|
|
|
|
display->next = *pHead;
|
|
*pHead = display;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* add_layout() - add a layout section to the XConfigPtr
|
|
*/
|
|
|
|
static void add_layout(GenerateOptions *gop, XConfigPtr config)
|
|
{
|
|
XConfigLayoutPtr layout;
|
|
XConfigAdjacencyPtr adj;
|
|
XConfigScreenPtr screen;
|
|
|
|
/* assume 1 X screen */
|
|
|
|
screen = xconfigGenerateAddScreen(config, -1, -1, -1, NULL, 0,
|
|
"nvidia", "NVIDIA Corporation");
|
|
|
|
/* create layout */
|
|
|
|
layout = xconfigAlloc(sizeof(XConfigLayoutRec));
|
|
|
|
layout->identifier = xconfigStrdup("Layout0");
|
|
|
|
adj = xconfigAlloc(sizeof(XConfigAdjacencyRec));
|
|
|
|
adj->scrnum = 0;
|
|
adj->screen = screen;
|
|
adj->screen_name = xconfigStrdup(screen->identifier);
|
|
|
|
layout->adjacencies = adj;
|
|
|
|
xconfigGenerateAssignScreenAdjacencies(layout);
|
|
|
|
add_inputref(config, layout, MOUSE_IDENTIFER, "CorePointer");
|
|
add_inputref(config, layout, KEYBOARD_IDENTIFER, "CoreKeyboard");
|
|
|
|
layout->next = config->layouts;
|
|
config->layouts = layout;
|
|
|
|
} /* add_layout() */
|
|
|
|
|
|
|
|
/*
|
|
* add_inputref() - add a new XConfigInputrefPtr to the given layout
|
|
*/
|
|
|
|
static void add_inputref(XConfigPtr config, XConfigLayoutPtr layout,
|
|
char *name, char *coreKeyword)
|
|
{
|
|
XConfigInputrefPtr inputRef;
|
|
|
|
inputRef = xconfigAlloc(sizeof(XConfigInputrefRec));
|
|
inputRef->input_name = xconfigStrdup(name);
|
|
inputRef->input = xconfigFindInput(inputRef->input_name, config->inputs);
|
|
inputRef->options = NULL;
|
|
xconfigAddNewOption(&inputRef->options, coreKeyword, NULL);
|
|
inputRef->next = layout->inputs;
|
|
layout->inputs = inputRef;
|
|
|
|
} /* add_inputref() */
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
* Mouse detection
|
|
*/
|
|
|
|
|
|
typedef struct {
|
|
char *shortname; /* commandline name */
|
|
char *name; /* mouse name */
|
|
char *gpmproto; /* protocol used by gpm */
|
|
char *Xproto; /* XFree86 Protocol */
|
|
char *device; /* /dev/ file */
|
|
int emulate3; /* Emulate3Buttons */
|
|
} MouseEntry;
|
|
|
|
|
|
/*
|
|
* This table is based on data contained in
|
|
* /usr/lib/python2.2/site-packages/rhpl/mouse.py on Red Hat Fedora
|
|
* core 1. That file contains the following copyright:
|
|
*
|
|
*
|
|
* mouse.py: mouse configuration data
|
|
*
|
|
* Copyright 1999-2002 Red Hat, Inc.
|
|
*/
|
|
|
|
static const MouseEntry __mice[] = {
|
|
/* shortname name gpm protocol X protocol device emulate3 */
|
|
{ "alpsps/2", "ALPS - GlidePoint (PS/2)", "ps/2", "GlidePointPS/2", "psaux", TRUE },
|
|
{ "ascii", "ASCII - MieMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
|
|
{ "asciips/2", "ASCII - MieMouse (PS/2)", "ps/2", "NetMousePS/2", "psaux", TRUE },
|
|
{ "atibm", "ATI - Bus Mouse", "Busmouse", "BusMouse", "atibm", TRUE },
|
|
{ "generic", "Generic - 2 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
|
|
{ "generic3", "Generic - 3 Button Mouse (serial)", "Microsoft", "Microsoft", "ttyS", FALSE },
|
|
{ "genericps/2", "Generic - 2 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", TRUE },
|
|
{ "generic3ps/2", "Generic - 3 Button Mouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
|
|
{ "genericwheelps/2", "Generic - Wheel Mouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
|
|
{ "genericusb", "Generic - 2 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", TRUE },
|
|
{ "generic3usb", "Generic - 3 Button Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
|
|
{ "genericwheelusb", "Generic - Wheel Mouse (USB)", "imps2", "IMPS/2", "input/mice", FALSE },
|
|
{ "geniusnm", "Genius - NetMouse (serial)", "ms3", "IntelliMouse", "ttyS", TRUE },
|
|
{ "geniusnmps/2", "Genius - NetMouse (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
|
|
{ "geniusprops/2", "Genius - NetMouse Pro (PS/2)", "netmouse", "NetMousePS/2", "psaux", TRUE },
|
|
{ "geniusscrollps/2", "Genius - NetScroll (PS/2)", "netmouse", "NetScrollPS/2", "psaux", TRUE },
|
|
{ "geniusscrollps/2+", "Genius - NetScroll+ (PS/2)", "netmouse", "NetMousePS/2", "psaux", FALSE },
|
|
{ "thinking", "Kensington - Thinking Mouse (serial)", "Microsoft", "ThinkingMouse", "ttyS", TRUE },
|
|
{ "thinkingps/2", "Kensington - Thinking Mouse (PS/2)", "ps/2", "ThinkingMousePS/2", "psaux", TRUE },
|
|
{ "logitech", "Logitech - C7 Mouse (serial, old C7 type)", "Logitech", "Logitech", "ttyS", FALSE },
|
|
{ "logitechcc", "Logitech - CC Series (serial)", "logim", "MouseMan", "ttyS", FALSE },
|
|
{ "logibm", "Logitech - Bus Mouse", "Busmouse", "BusMouse", "logibm", FALSE },
|
|
{ "logimman", "Logitech - MouseMan/FirstMouse (serial)", "MouseMan", "MouseMan", "ttyS", FALSE },
|
|
{ "logimmanps/2", "Logitech - MouseMan/FirstMouse (PS/2)", "ps/2", "PS/2", "psaux", FALSE },
|
|
{ "logimman+", "Logitech - MouseMan+/FirstMouse+ (serial)", "pnp", "IntelliMouse", "ttyS", FALSE },
|
|
{ "logimman+ps/2", "Logitech - MouseMan+/FirstMouse+ (PS/2)", "ps/2", "MouseManPlusPS/2", "psaux", FALSE },
|
|
{ "logimmusb", "Logitech - MouseMan Wheel (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
|
|
{ "logimmusboptical", "Logitech - Cordless Optical Mouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
|
|
{ "microsoft", "Microsoft - Compatible Mouse (serial)", "Microsoft", "Microsoft", "ttyS", TRUE },
|
|
{ "msnew", "Microsoft - Rev 2.1A or higher (serial)", "pnp", "Auto", "ttyS", TRUE },
|
|
{ "msintelli", "Microsoft - IntelliMouse (serial)", "ms3", "IntelliMouse", "ttyS", FALSE },
|
|
{ "msintellips/2", "Microsoft - IntelliMouse (PS/2)", "imps2", "IMPS/2", "psaux", FALSE },
|
|
{ "msintelliusb", "Microsoft - IntelliMouse (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
|
|
{ "msintelliusboptical","Microsoft - IntelliMouse Optical (USB)", "ps/2", "IMPS/2", "input/mice", FALSE },
|
|
{ "msbm", "Microsoft - Bus Mouse", "Busmouse", "BusMouse", "inportbm", TRUE },
|
|
{ "mousesystems", "Mouse Systems - Mouse (serial)", "MouseSystems", "MouseSystems", "ttyS", TRUE },
|
|
{ "mmseries", "MM - Series (serial)", "MMSeries", "MMSeries", "ttyS", TRUE },
|
|
{ "mmhittab", "MM - HitTablet (serial)", "MMHitTab", "MMHittab", "ttyS", TRUE },
|
|
{ "sun", "Sun - Mouse", "sun", "sun", "sunmouse", FALSE },
|
|
{ NULL, NULL, NULL, NULL, NULL, FALSE },
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* This table maps between the mouse protocol name used for gpm and
|
|
* for the X server "protocol" mouse option.
|
|
*/
|
|
|
|
typedef struct {
|
|
char *gpmproto;
|
|
char *Xproto;
|
|
} ProtocolEntry;
|
|
|
|
static const ProtocolEntry __protocols[] = {
|
|
/* gpm protocol X protocol */
|
|
{ "ms3", "IntelliMouse" },
|
|
{ "Busmouse", "BusMouse" },
|
|
{ "Microsoft", "Microsoft" },
|
|
{ "imps2", "IMPS/2" },
|
|
{ "netmouse", "NetMousePS/2" },
|
|
{ "Logitech", "Logitech" },
|
|
{ "logim", "MouseMan" },
|
|
{ "MouseMan", "MouseMan" },
|
|
{ "ps/2", "PS/2" },
|
|
{ "pnp", "Auto" },
|
|
{ "MouseSystems", "MouseSystems" },
|
|
{ "MMSeries", "MMSeries" },
|
|
{ "MMHitTab", "MMHittab" },
|
|
{ "sun", "sun" },
|
|
{ NULL, NULL },
|
|
};
|
|
|
|
|
|
/*
|
|
* gpm_proto_to_X_proto() - map from gpm mouse protocol to X mouse
|
|
* protocol
|
|
*/
|
|
|
|
static char* gpm_proto_to_X_proto(const char *gpm)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; __protocols[i].gpmproto; i++) {
|
|
if (strcmp(gpm, __protocols[i].gpmproto) == 0) {
|
|
return __protocols[i].Xproto;
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
} /* gpm_proto_to_X_proto() */
|
|
|
|
|
|
|
|
/*
|
|
* find_mouse_entry() - scan the __mice[] table for the entry that
|
|
* corresponds to the specified value; return a pointer to the
|
|
* matching entry in the table, if any.
|
|
*/
|
|
|
|
static const MouseEntry *find_mouse_entry(char *value)
|
|
{
|
|
int i;
|
|
|
|
if (!value) return NULL;
|
|
|
|
for (i = 0; __mice[i].name; i++) {
|
|
if (strcmp(value, __mice[i].shortname) == 0) {
|
|
return &__mice[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
} /* find_mouse_entry() */
|
|
|
|
|
|
|
|
/*
|
|
* find_closest_mouse_entry() - scan the __mice[] table for the entry that
|
|
* matches all of the specified values; any of the values can be NULL,
|
|
* in which case we do not use them as part of the comparison. Note
|
|
* that device is compared case sensitive, proto is compared case
|
|
* insensitive, and emulate3 is just a boolean.
|
|
*/
|
|
|
|
static const MouseEntry *find_closest_mouse_entry(const char *device,
|
|
const char *proto,
|
|
const char *emulate3_str)
|
|
{
|
|
int i;
|
|
int emulate3 = FALSE;
|
|
|
|
/*
|
|
* translate the emulate3 string into a boolean we can use below
|
|
* for comparison
|
|
*/
|
|
|
|
if ((emulate3_str) &&
|
|
((strcasecmp(emulate3_str, "yes") == 0) ||
|
|
(strcasecmp(emulate3_str, "true") == 0) ||
|
|
(strcasecmp(emulate3_str, "1") == 0))) {
|
|
emulate3 = TRUE;
|
|
}
|
|
|
|
/*
|
|
* skip the "/dev/" part of the device filename
|
|
*/
|
|
|
|
if (device && (strncmp(device, "/dev/", 5) == 0)) {
|
|
device += 5; /* strlen("/dev/") */
|
|
}
|
|
|
|
for (i = 0; __mice[i].name; i++) {
|
|
if ((device) && (strcmp(device, __mice[i].device) != 0)) continue;
|
|
if ((proto) && (strcasecmp(proto, __mice[i].Xproto)) != 0) continue;
|
|
if ((emulate3_str) && (emulate3 != __mice[i].emulate3)) continue;
|
|
return &__mice[i];
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} /* find_closest_mouse_entry() */
|
|
|
|
|
|
|
|
/*
|
|
* find_config_entry() - scan the specified filename for the specified
|
|
* keyword; return the value that the keyword is assigned to, or NULL
|
|
* if any error occurs.
|
|
*/
|
|
|
|
static char *find_config_entry(const char *filename, const char *keyword)
|
|
{
|
|
int fd = -1;
|
|
char *data = NULL;
|
|
char *value = NULL;
|
|
char *buf = NULL;
|
|
char *tmp, *start, *c, *end;
|
|
struct stat stat_buf;
|
|
size_t len;
|
|
|
|
if ((fd = open(filename, O_RDONLY)) == -1) goto done;
|
|
|
|
if (fstat(fd, &stat_buf) == -1) goto done;
|
|
|
|
if ((data = mmap(0, stat_buf.st_size, PROT_READ, MAP_SHARED,
|
|
fd, 0)) == (void *) -1) goto done;
|
|
|
|
/*
|
|
* create a sysmem copy of the buffer, so that we can explicitly
|
|
* NULL terminate it
|
|
*/
|
|
|
|
buf = malloc(stat_buf.st_size + 1);
|
|
|
|
if (!buf) goto done;
|
|
|
|
memcpy(buf, data, stat_buf.st_size);
|
|
buf[stat_buf.st_size] = '\0';
|
|
|
|
/* search for the keyword */
|
|
|
|
start = buf;
|
|
|
|
while (TRUE) {
|
|
tmp = strstr(start, keyword);
|
|
if (!tmp) goto done;
|
|
|
|
/*
|
|
* make sure this line is not commented out: search back from
|
|
* tmp: if we hit a "#" before a newline, then this line is
|
|
* commented out and we should search again
|
|
*/
|
|
|
|
c = tmp;
|
|
while ((c >= start) && (*c != '\n') && (*c != '#')) c--;
|
|
|
|
if (*c == '#') {
|
|
/* keyword was commented out... search again */
|
|
start = tmp+1;
|
|
} else {
|
|
/* keyword is not commented out */
|
|
break;
|
|
}
|
|
}
|
|
|
|
start = tmp + strlen(keyword);
|
|
end = strchr(start, '\n');
|
|
if (!end) goto done;
|
|
|
|
/* there must be something between the start and the end */
|
|
|
|
if (start == end) goto done;
|
|
|
|
/* take what is between as the value */
|
|
|
|
len = end - start;
|
|
value = xconfigAlloc(len + 1);
|
|
strncpy(value, start, len);
|
|
value[len] = '\0';
|
|
|
|
/* if the first and last characters are quotation marks, remove them */
|
|
|
|
if ((value[0] == '\"') && (value[len-1] == '\"')) {
|
|
tmp = xconfigAlloc(len - 1);
|
|
strncpy(tmp, value + 1, len - 2);
|
|
tmp[len-2] = '\0';
|
|
free(value);
|
|
value = tmp;
|
|
}
|
|
|
|
done:
|
|
|
|
if (buf) free(buf);
|
|
if (data) munmap(data, stat_buf.st_size);
|
|
if (fd != -1) close(fd);
|
|
|
|
return value;
|
|
|
|
} /* find_config_entry() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGeneratePrintPossibleMice() - print the mouse table to stdout
|
|
*/
|
|
|
|
void xconfigGeneratePrintPossibleMice(void)
|
|
{
|
|
int i;
|
|
|
|
printf("%-25s%-35s\n\n", "Short Name", "Name");
|
|
|
|
for (i = 0; __mice[i].name; i++) {
|
|
printf("%-25s%-35s\n", __mice[i].shortname, __mice[i].name);
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
} /* xconfigGeneratePrintPossibleMice() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigAddMouse() - determine the mouse type, and then add an
|
|
* XConfigInputRec with the appropriate options.
|
|
*
|
|
* - if the user specified on the commandline, use that
|
|
*
|
|
* - if /etc/sysconfig/mouse exists and contains valid data, use
|
|
* that
|
|
*
|
|
* - if /etc/conf.d/gpm exists and contains valid data, use that
|
|
*
|
|
* - infer the settings from the commandline options gpm is using XXX?
|
|
*
|
|
* - default to "auto" on /dev/mouse
|
|
*/
|
|
|
|
int xconfigAddMouse(GenerateOptions *gop, XConfigPtr config)
|
|
{
|
|
const MouseEntry *entry = NULL;
|
|
XConfigInputPtr input;
|
|
char *device_path, *comment = "default";
|
|
|
|
/* if the user specified on the commandline, use that */
|
|
|
|
if (gop->mouse) {
|
|
entry = find_mouse_entry(gop->mouse);
|
|
if (entry) {
|
|
comment = "commandline input";
|
|
} else {
|
|
xconfigErrorMsg(WarnMsg, "Unable to find mouse \"%s\".",
|
|
gop->mouse);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if /etc/sysconfig/mouse exists, and contains valid data, use
|
|
* that
|
|
*/
|
|
|
|
if (!entry) {
|
|
char *protocol, *device, *emulate3;
|
|
|
|
device = find_config_entry("/etc/sysconfig/mouse", "DEVICE=");
|
|
protocol = find_config_entry("/etc/sysconfig/mouse", "XMOUSETYPE=");
|
|
emulate3 = find_config_entry("/etc/sysconfig/mouse", "XEMU3=");
|
|
|
|
if (device || protocol || emulate3) {
|
|
entry = find_closest_mouse_entry(device, protocol, emulate3);
|
|
if (entry) {
|
|
comment = "data in \"/etc/sysconfig/mouse\"";
|
|
}
|
|
}
|
|
}
|
|
|
|
/* if /etc/conf.d/gpm exists and contains valid data, use that */
|
|
|
|
if (!entry) {
|
|
char *protocol, *device;
|
|
|
|
protocol = find_config_entry("/etc/conf.d/gpm", "MOUSE=");
|
|
device = find_config_entry("/etc/conf.d/gpm", "MOUSEDEV=");
|
|
|
|
if (protocol && device) {
|
|
MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
|
|
e->shortname = "custom";
|
|
e->name = "inferred from /etc/conf.d/gpm";
|
|
e->gpmproto = protocol;
|
|
e->Xproto = gpm_proto_to_X_proto(protocol);
|
|
e->device = device + strlen("/dev/");
|
|
e->emulate3 = FALSE; // XXX?
|
|
entry = e;
|
|
comment = "data in \"/etc/conf.d/gpm\"";
|
|
}
|
|
}
|
|
|
|
/*
|
|
* XXX we could try to infer the settings from the commandline
|
|
* options gpm is using
|
|
*/
|
|
|
|
if (!entry) {
|
|
/* XXX implement me */
|
|
}
|
|
|
|
/* at this point, we must have a mouse entry */
|
|
|
|
if (!entry) {
|
|
MouseEntry *e = xconfigAlloc(sizeof(MouseEntry));
|
|
e->Xproto = "auto";
|
|
|
|
#if defined(NV_BSD)
|
|
e->device = "sysmouse";
|
|
#else
|
|
if (access("/dev/psaux", F_OK) == 0) {
|
|
e->device = "psaux";
|
|
} else if (access("/dev/input/mice", F_OK) == 0) {
|
|
e->device = "input/mice";
|
|
} else {
|
|
e->device = "mouse";
|
|
}
|
|
#endif
|
|
e->emulate3 = FALSE;
|
|
entry = e;
|
|
}
|
|
|
|
/* add a new mouse input section */
|
|
|
|
input = xconfigAlloc(sizeof(XConfigInputRec));
|
|
|
|
input->comment = xconfigStrcat(" # generated from ",
|
|
comment, "\n", NULL);
|
|
input->identifier = xconfigStrdup("Mouse0");
|
|
input->driver = xconfigStrdup("mouse");
|
|
|
|
device_path = xconfigStrcat("/dev/", entry->device, NULL);
|
|
|
|
input->options = NULL;
|
|
xconfigAddNewOption(&input->options, "Protocol", entry->Xproto);
|
|
xconfigAddNewOption(&input->options, "Device", device_path);
|
|
xconfigAddNewOption(&input->options, "Emulate3Buttons",
|
|
(entry->emulate3 ? "yes" : "no"));
|
|
TEST_FREE(device_path);
|
|
|
|
|
|
/*
|
|
* This will make wheel mice work, and non-wheel mice should
|
|
* ignore ZAxisMapping
|
|
*/
|
|
|
|
xconfigAddNewOption(&input->options, "ZAxisMapping", "4 5");
|
|
|
|
input->next = config->inputs;
|
|
config->inputs = input;
|
|
|
|
return TRUE;
|
|
|
|
} /* xconfigAddMouse() */
|
|
|
|
|
|
|
|
|
|
|
|
/*********************************************************************/
|
|
|
|
/*
|
|
* keyboard detection
|
|
*/
|
|
|
|
typedef struct {
|
|
char *keytable;
|
|
char *name;
|
|
char *layout; /* XkbLayout */
|
|
char *model; /* XkbModel */
|
|
char *variant; /* XkbVariant */
|
|
char *options; /* XkbOptions */
|
|
} KeyboardEntry;
|
|
|
|
|
|
/*
|
|
* This table is based on data contained in
|
|
* /usr/lib/python2.2/site-packages/rhpl/keyboard_models.py on Red Hat
|
|
* Fedora core 1. That file contains the following copyright:
|
|
*
|
|
*
|
|
* keyboard_models.py - keyboard model list
|
|
*
|
|
* Brent Fox <bfox@redhat.com>
|
|
* Mike Fulbright <msf@redhat.com>
|
|
* Jeremy Katz <katzj@redhat.com>
|
|
*
|
|
* Copyright 2002 Red Hat, Inc.
|
|
*/
|
|
|
|
static const KeyboardEntry __keyboards[] = {
|
|
|
|
/* keytable name layout model variant options */
|
|
|
|
{ "be-latin1", "Belgian (be-latin1)", "be", "pc105", NULL, NULL },
|
|
{ "bg", "Bulgarian", "bg,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "br-abnt2", "Brazilian (ABNT2)", "br", "abnt2", NULL, NULL },
|
|
{ "cf", "French Canadian", "ca_enhanced", "pc105", NULL, NULL },
|
|
{ "croat", "Croatian", "hr", "pc105", NULL, NULL },
|
|
{ "cz-us-qwertz", "Czechoslovakian (qwertz)", "cz,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "cz-lat2", "Czechoslovakian", "cz_qwerty", "pc105", NULL, NULL },
|
|
{ "de", "German", "de", "pc105", NULL, NULL },
|
|
{ "de-latin1", "German (latin1)", "de", "pc105", NULL, NULL },
|
|
{ "de-latin1-nodeadkeys", "German (latin1 w/ no deadkeys)", "de", "pc105", "nodeadkeys", NULL },
|
|
{ "dvorak", "Dvorak", "dvorak", "pc105", NULL, NULL },
|
|
{ "dk", "Danish", "dk", "pc105", NULL, NULL },
|
|
{ "dk-latin1", "Danish (latin1)", "dk", "pc105", NULL, NULL },
|
|
{ "es", "Spanish", "es", "pc105", NULL, NULL },
|
|
{ "et", "Estonian", "ee", "pc105", NULL, NULL },
|
|
{ "fi", "Finnish", "fi", "pc105", NULL, NULL },
|
|
{ "fi-latin1", "Finnish (latin1)", "fi", "pc105", NULL, NULL },
|
|
{ "fr", "French", "fr", "pc105", NULL, NULL },
|
|
{ "fr-latin0", "French (latin0)", "fr", "pc105", NULL, NULL },
|
|
{ "fr-latin1", "French (latin1)", "fr", "pc105", NULL, NULL },
|
|
{ "fr-pc", "French (pc)", "fr", "pc105", NULL, NULL },
|
|
{ "fr_CH", "Swiss French", "fr_CH", "pc105", NULL, NULL },
|
|
{ "fr_CH-latin1", "Swiss French (latin1)", "fr_CH", "pc105", NULL, NULL },
|
|
{ "gr", "Greek", "us,el", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "hu", "Hungarian", "hu", "pc105", NULL, NULL },
|
|
{ "hu101", "Hungarian (101 key)", "hu", "pc105", NULL, NULL },
|
|
{ "is-latin1", "Icelandic", "is", "pc105", NULL, NULL },
|
|
{ "it", "Italian", "it", "pc105", NULL, NULL },
|
|
{ "it-ibm", "Italian (IBM)", "it", "pc105", NULL, NULL },
|
|
{ "it2", "Italian (it2)", "it", "pc105", NULL, NULL },
|
|
{ "jp106", "Japanese", "jp", "jp106", NULL, NULL },
|
|
{ "la-latin1", "Latin American", "la", "pc105", NULL, NULL },
|
|
{ "mk-utf", "Macedonian", "mk,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "no", "Norwegian", "no", "pc105", NULL, NULL },
|
|
{ "pl", "Polish", "pl", "pc105", NULL, NULL },
|
|
{ "pt-latin1", "Portuguese", "pt", "pc105", NULL, NULL },
|
|
{ "ro_win", "Romanian", "ro", "pc105", NULL, NULL },
|
|
{ "ru", "Russian", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "ru-cp1251", "Russian (cp1251)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "ru-ms", "Russian (Microsoft)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "ru1", "Russian (ru1)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "ru2", "Russian (ru2)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "ru_win", "Russian (win)", "ru,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "speakup", "Speakup", "us", "pc105", NULL, NULL },
|
|
{ "speakup-lt", "Speakup (laptop)", "us", "pc105", NULL, NULL },
|
|
{ "sv-latin1", "Swedish", "se", "pc105", NULL, NULL },
|
|
{ "sg", "Swiss German", "de_CH", "pc105", NULL, NULL },
|
|
{ "sg-latin1", "Swiss German (latin1)", "de_CH", "pc105", NULL, NULL },
|
|
{ "sk-qwerty", "Slovakian", "sk_qwerty", "pc105", NULL, NULL },
|
|
{ "slovene", "Slovenian", "si", "pc105", NULL, NULL },
|
|
{ "trq", "Turkish", "tr", "pc105", NULL, NULL },
|
|
{ "uk", "United Kingdom", "gb", "pc105", NULL, NULL },
|
|
{ "ua", "Ukrainian", "ua,us", "pc105", NULL, "grp:shift_toggle,grp_led:scroll" },
|
|
{ "us-acentos", "U.S. International", "us_intl", "pc105", NULL, NULL },
|
|
{ "us", "U.S. English", "us", "pc105", NULL, NULL },
|
|
{ NULL, NULL, NULL, NULL, NULL, NULL },
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
* find_keyboard_entry() - scan the __keyboards[] table for the entry that
|
|
* corresponds to the specified value; return a pointer to the
|
|
* matching entry in the table, if any.
|
|
*/
|
|
|
|
static const KeyboardEntry *find_keyboard_entry(char *value)
|
|
{
|
|
int i;
|
|
|
|
if (!value) return NULL;
|
|
|
|
for (i = 0; __keyboards[i].name; i++) {
|
|
if (strcmp(value, __keyboards[i].keytable) == 0) {
|
|
return &__keyboards[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
|
|
} /* find_keyboard_entry() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGeneratePrintPossibleKeyboards() - print the keyboard table
|
|
*/
|
|
|
|
void xconfigGeneratePrintPossibleKeyboards(void)
|
|
{
|
|
int i;
|
|
|
|
printf("%-25s%-35s\n\n", "Short Name", "Name");
|
|
|
|
for (i = 0; __keyboards[i].name; i++) {
|
|
printf("%-25s%-35s\n", __keyboards[i].keytable, __keyboards[i].name);
|
|
}
|
|
|
|
printf("\n");
|
|
|
|
} /* xconfigGeneratePrintPossibleKeyboards() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigAddKeyboard() - determine the keyboard type, and then add an
|
|
* XConfigInputRec with the appropriate options.
|
|
*
|
|
* How to detect the keyboard:
|
|
*
|
|
* - if the user specified on the command line, use that
|
|
*
|
|
* - if /etc/sysconfig/keyboard exists, and contains a valid
|
|
* KEYTABLE entry, use that
|
|
*/
|
|
|
|
int xconfigAddKeyboard(GenerateOptions *gop, XConfigPtr config)
|
|
{
|
|
char *value, *comment = "default";
|
|
const KeyboardEntry *entry = NULL;
|
|
|
|
XConfigInputPtr input;
|
|
|
|
/*
|
|
* if the user specified on the command line, use that
|
|
*/
|
|
|
|
if (gop->keyboard) {
|
|
entry = find_keyboard_entry(gop->keyboard);
|
|
if (entry) {
|
|
comment = "commandline input";
|
|
} else {
|
|
xconfigErrorMsg(WarnMsg, "Unable to find keyboard \"%s\".",
|
|
gop->keyboard);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* if /etc/sysconfig/keyboard exists, and contains a valid
|
|
* KEYTABLE entry, use that
|
|
*/
|
|
|
|
if (!entry) {
|
|
value = find_config_entry("/etc/sysconfig/keyboard", "KEYTABLE=");
|
|
entry = find_keyboard_entry(value);
|
|
if (value) {
|
|
free(value);
|
|
}
|
|
if (entry) {
|
|
comment = "data in \"/etc/sysconfig/keyboard\"";
|
|
}
|
|
}
|
|
|
|
/* add a new keyboard input section */
|
|
|
|
input = xconfigAlloc(sizeof(XConfigInputRec));
|
|
|
|
input->comment = xconfigStrcat(" # generated from ",
|
|
comment, "\n", NULL);
|
|
input->identifier = xconfigStrdup("Keyboard0");
|
|
|
|
/*
|
|
* determine which keyboard driver should be used (either "kbd" or
|
|
* "keyboard"); if the user specified a keyboard driver use that;
|
|
* if 'ROOT/lib/modules/input/kbd_drv.(o|so)' exists, use "kbd";
|
|
* otherwise, use "keyboard".
|
|
* On Solaris, use the default "keyboard"
|
|
*/
|
|
|
|
if (gop->keyboard_driver) {
|
|
input->driver = gop->keyboard_driver;
|
|
} else {
|
|
#if defined(NV_SUNOS) || defined(NV_BSD)
|
|
input->driver = xconfigStrdup("keyboard");
|
|
#else
|
|
input->driver = xconfigStrdup("kbd");
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
* set additional keyboard options, based on the Keyboard table
|
|
* entry we found above
|
|
*/
|
|
|
|
input->options = NULL;
|
|
|
|
if (entry) {
|
|
if (entry->layout)
|
|
xconfigAddNewOption(&input->options, "XkbLayout", entry->layout);
|
|
if (entry->model)
|
|
xconfigAddNewOption(&input->options, "XkbModel", entry->model);
|
|
if (entry->variant)
|
|
xconfigAddNewOption(&input->options, "XkbVariant", entry->variant);
|
|
if (entry->options)
|
|
xconfigAddNewOption(&input->options, "XkbOptions", entry->options);
|
|
}
|
|
|
|
input->next = config->inputs;
|
|
config->inputs = input;
|
|
|
|
return TRUE;
|
|
|
|
} /* xconfigAddKeyboard() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGetDefaultProjectRoot() - scan some common directories for the X
|
|
* project root.
|
|
*
|
|
* Users of this information should be careful to account for the
|
|
* modular layout.
|
|
*/
|
|
|
|
static char *xconfigGetDefaultProjectRoot(void)
|
|
{
|
|
char *paths[] = { "/usr/X11R6", "/usr/X11", NULL };
|
|
struct stat stat_buf;
|
|
int i;
|
|
|
|
for (i = 0; paths[i]; i++) {
|
|
|
|
if (stat(paths[i], &stat_buf) == -1) {
|
|
continue;
|
|
}
|
|
|
|
if (S_ISDIR(stat_buf.st_mode)) {
|
|
return paths[i];
|
|
}
|
|
}
|
|
|
|
/* default to "/usr/X11R6", I guess */
|
|
|
|
return paths[0];
|
|
|
|
} /* xconfigGetDefaultProjectRoot() */
|
|
|
|
|
|
|
|
|
|
/*
|
|
* get_xserver_information() - parse the versionString (from `X
|
|
* -version`) and assign relevant information that we infer from the X
|
|
* server version.
|
|
*/
|
|
|
|
static int get_xserver_information(const char *versionString,
|
|
int *autoloadsGLX,
|
|
int *supportsExtensionSection,
|
|
int *xineramaPlusCompositeWorks,
|
|
const char **compositeExtensionName)
|
|
{
|
|
#define XSERVER_VERSION_FORMAT_1 "X Window System Version"
|
|
#define XSERVER_VERSION_FORMAT_2 "X.Org X Server"
|
|
|
|
int major, minor, found;
|
|
const char *ptr;
|
|
|
|
/* check if this is an XFree86 X server */
|
|
|
|
if (strstr(versionString, "XFree86 Version")) {
|
|
xconfigErrorMsg(WarnMsg, "XFree86 is not supported.");
|
|
return FALSE;
|
|
}
|
|
|
|
/* attempt to parse the major.minor version out of the string */
|
|
|
|
found = FALSE;
|
|
|
|
if (((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_1)) != NULL) &&
|
|
(sscanf(ptr, XSERVER_VERSION_FORMAT_1 " %d.%d", &major, &minor) == 2)) {
|
|
found = TRUE;
|
|
}
|
|
|
|
if (!found &&
|
|
((ptr = strstr(versionString, XSERVER_VERSION_FORMAT_2)) != NULL) &&
|
|
(sscanf(ptr, XSERVER_VERSION_FORMAT_2 " %d.%d", &major, &minor) == 2)) {
|
|
found = TRUE;
|
|
}
|
|
|
|
/* if we can't parse the version, give up */
|
|
|
|
if (!found) return FALSE;
|
|
|
|
/*
|
|
* supportsExtensionSection: support for the "Extension" xorg.conf
|
|
* section was added between X.Org 6.7 and 6.8. To account for
|
|
* the X server version wrap, it is easier to check for X servers
|
|
* that do not support the Extension section: 6.x (x < 8) X
|
|
* servers.
|
|
*/
|
|
|
|
if ((major == 6) && (minor < 8)) {
|
|
*supportsExtensionSection = FALSE;
|
|
} else {
|
|
*supportsExtensionSection = TRUE;
|
|
}
|
|
|
|
/*
|
|
* support for autoloading GLX was added in X.Org 1.5. To account
|
|
* for the X server version wrap, it is easier to check for X
|
|
* servers that do not support GLX autoloading: 6.x, 7.x, or < 1.5
|
|
* X servers.
|
|
*/
|
|
|
|
if ((major == 6) || (major == 7) || ((major == 1) && (minor < 5))) {
|
|
*autoloadsGLX = FALSE;
|
|
} else {
|
|
*autoloadsGLX = TRUE;
|
|
}
|
|
|
|
/*
|
|
* support for Xinerama and Composite at the same time works on X.Org
|
|
* xserver 1.15.
|
|
*/
|
|
|
|
if ((major == 6) || (major == 7) || ((major == 1) && (minor < 15))) {
|
|
*xineramaPlusCompositeWorks = FALSE;
|
|
} else {
|
|
*xineramaPlusCompositeWorks = TRUE;
|
|
}
|
|
|
|
/*
|
|
* With X.Org xserver version 1.20, the name of the composite
|
|
* extension was changed from "Composite" to "COMPOSITE". As of
|
|
* that release extension names are case-sensitive so we must
|
|
* ensure the correct case is used.
|
|
*/
|
|
if (major == 1 && minor >= 20) {
|
|
*compositeExtensionName = "COMPOSITE";
|
|
} else {
|
|
*compositeExtensionName = "Composite";
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
} /* get_xserver_information() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGetXServerInUse() - try to determine which X server is in use
|
|
* (XFree86, Xorg); also determine if the X server supports the
|
|
* Extension section of the X config file; support for the "Extension"
|
|
* section was added between X.Org 6.7 and 6.8.
|
|
*
|
|
* Some of the parsing here mimics what is done in the
|
|
* check_for_modular_xorg() function in nvidia-installer
|
|
*/
|
|
|
|
#define NV_LINE_LEN 1024
|
|
#define EXTRA_PATH "/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin:/usr/bin/X11"
|
|
#if defined(NV_SUNOS)
|
|
#define XSERVER_BIN_NAME "Xorg"
|
|
#else
|
|
#define XSERVER_BIN_NAME "X"
|
|
#endif
|
|
|
|
|
|
void xconfigGetXServerInUse(GenerateOptions *gop)
|
|
{
|
|
FILE *stream = NULL;
|
|
int len, found;
|
|
char *cmd, *ptr, *ret;
|
|
|
|
gop->supports_extension_section = FALSE;
|
|
gop->autoloads_glx = FALSE;
|
|
gop->xinerama_plus_composite_works = FALSE;
|
|
gop->compositeExtensionName = NULL;
|
|
|
|
/* run `X -version` with a PATH that hopefully includes the X binary */
|
|
|
|
cmd = xconfigStrcat("PATH=", gop->x_project_root, ":",
|
|
EXTRA_PATH, ":$PATH ", XSERVER_BIN_NAME,
|
|
" -version 2>&1", NULL);
|
|
|
|
if ((stream = popen(cmd, "r"))) {
|
|
char buf[NV_LINE_LEN];
|
|
|
|
/* read in as much of the input as we can fit into the buffer */
|
|
|
|
ptr = buf;
|
|
|
|
do {
|
|
len = NV_LINE_LEN - (ptr - buf) - 1;
|
|
ret = fgets(ptr, len, stream);
|
|
ptr = strchr(ptr, '\0');
|
|
} while ((ret != NULL) && (len > 1));
|
|
|
|
/*
|
|
* process the `X -version` output to infer relevant
|
|
* information from this X server
|
|
*/
|
|
|
|
found = get_xserver_information(buf,
|
|
&gop->autoloads_glx,
|
|
&gop->supports_extension_section,
|
|
&gop->xinerama_plus_composite_works,
|
|
&gop->compositeExtensionName);
|
|
|
|
if (!found) {
|
|
xconfigErrorMsg(WarnMsg, "Unable to parse X.Org version string.");
|
|
}
|
|
}
|
|
/* Close the popen()'ed stream. */
|
|
pclose(stream);
|
|
free(cmd);
|
|
|
|
} /* xconfigGetXServerInUse() */
|
|
|
|
|
|
|
|
/*
|
|
* xconfigGenerateLoadDefaultOptions - initialize a GenerateOptions
|
|
* structure with default values by peeking at the file system.
|
|
*/
|
|
|
|
void xconfigGenerateLoadDefaultOptions(GenerateOptions *gop)
|
|
{
|
|
memset(gop, 0, sizeof(GenerateOptions));
|
|
|
|
gop->x_project_root = xconfigGetDefaultProjectRoot();
|
|
|
|
/* XXX What to default the following to?
|
|
gop->keyboard
|
|
gop->mouse
|
|
gop->keyboard_driver
|
|
*/
|
|
|
|
} /* xconfigGenerateLoadDefaultOptions() */
|