| 1 | /* |
| 2 | * Copyright 2000-2002 by Alan Hourihane, Flint Mountain, North Wales. |
| 3 | * |
| 4 | * Permission to use, copy, modify, distribute, and sell this software and its |
| 5 | * documentation for any purpose is hereby granted without fee, provided that |
| 6 | * the above copyright notice appear in all copies and that both that |
| 7 | * copyright notice and this permission notice appear in supporting |
| 8 | * documentation, and that the name of Alan Hourihane not be used in |
| 9 | * advertising or publicity pertaining to distribution of the software without |
| 10 | * specific, written prior permission. Alan Hourihane makes no representations |
| 11 | * about the suitability of this software for any purpose. It is provided |
| 12 | * "as is" without express or implied warranty. |
| 13 | * |
| 14 | * ALAN HOURIHANE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
| 16 | * EVENT SHALL ALAN HOURIHANE BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
| 20 | * PERFORMANCE OF THIS SOFTWARE. |
| 21 | * |
| 22 | * Author: Alan Hourihane, alanh@fairlite.demon.co.uk |
| 23 | * |
| 24 | */ |
| 25 | |
| 26 | #ifdef HAVE_XORG_CONFIG_H |
| 27 | #include <xorg-config.h> |
| 28 | #endif |
| 29 | |
| 30 | #include "xf86.h" |
| 31 | #include "xf86Config.h" |
| 32 | #include "xf86_OSlib.h" |
| 33 | #include "xf86Priv.h" |
| 34 | #define IN_XSERVER |
| 35 | #include "Configint.h" |
| 36 | #include "xf86DDC.h" |
| 37 | #include "xf86pciBus.h" |
| 38 | #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) |
| 39 | #include "xf86Bus.h" |
| 40 | #include "xf86Sbus.h" |
| 41 | #endif |
| 42 | #include "misc.h" |
| 43 | |
| 44 | typedef struct _DevToConfig { |
| 45 | GDevRec GDev; |
| 46 | struct pci_device *pVideo; |
| 47 | #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) |
| 48 | sbusDevicePtr sVideo; |
| 49 | #endif |
| 50 | int iDriver; |
| 51 | } DevToConfigRec, *DevToConfigPtr; |
| 52 | |
| 53 | static DevToConfigPtr DevToConfig = NULL; |
| 54 | static int nDevToConfig = 0, CurrentDriver; |
| 55 | |
| 56 | xf86MonPtr ConfiguredMonitor; |
| 57 | Bool xf86DoConfigurePass1 = TRUE; |
| 58 | static Bool foundMouse = FALSE; |
| 59 | |
| 60 | #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) |
| 61 | static const char *DFLT_MOUSE_DEV = "/dev/sysmouse"; |
| 62 | static const char *DFLT_MOUSE_PROTO = "auto"; |
| 63 | #elif defined(linux) |
| 64 | static const char *DFLT_MOUSE_DEV = "/dev/input/mice"; |
| 65 | static const char *DFLT_MOUSE_PROTO = "auto"; |
| 66 | #elif defined(WSCONS_SUPPORT) |
| 67 | static const char *DFLT_MOUSE_DEV = "/dev/wsmouse"; |
| 68 | static const char *DFLT_MOUSE_PROTO = "wsmouse"; |
| 69 | #else |
| 70 | static const char *DFLT_MOUSE_DEV = "/dev/mouse"; |
| 71 | static const char *DFLT_MOUSE_PROTO = "auto"; |
| 72 | #endif |
| 73 | |
| 74 | /* |
| 75 | * This is called by the driver, either through xf86Match???Instances() or |
| 76 | * directly. We allocate a GDevRec and fill it in as much as we can, letting |
| 77 | * the caller fill in the rest and/or change it as it sees fit. |
| 78 | */ |
| 79 | GDevPtr |
| 80 | xf86AddBusDeviceToConfigure(const char *driver, BusType bus, void *busData, |
| 81 | int chipset) |
| 82 | { |
| 83 | int ret, i, j; |
| 84 | |
| 85 | if (!xf86DoConfigure || !xf86DoConfigurePass1) |
| 86 | return NULL; |
| 87 | |
| 88 | /* Check for duplicates */ |
| 89 | for (i = 0; i < nDevToConfig; i++) { |
| 90 | switch (bus) { |
| 91 | #ifdef XSERVER_LIBPCIACCESS |
| 92 | case BUS_PCI: |
| 93 | ret = xf86PciConfigure(busData, DevToConfig[i].pVideo); |
| 94 | break; |
| 95 | #endif |
| 96 | #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) |
| 97 | case BUS_SBUS: |
| 98 | ret = xf86SbusConfigure(busData, DevToConfig[i].sVideo); |
| 99 | break; |
| 100 | #endif |
| 101 | default: |
| 102 | return NULL; |
| 103 | } |
| 104 | if (ret == 0) |
| 105 | goto out; |
| 106 | } |
| 107 | |
| 108 | /* Allocate new structure occurrence */ |
| 109 | i = nDevToConfig++; |
| 110 | DevToConfig = |
| 111 | xnfrealloc(DevToConfig, nDevToConfig * sizeof(DevToConfigRec)); |
| 112 | memset(DevToConfig + i, 0, sizeof(DevToConfigRec)); |
| 113 | |
| 114 | DevToConfig[i].GDev.chipID = |
| 115 | DevToConfig[i].GDev.chipRev = DevToConfig[i].GDev.irq = -1; |
| 116 | |
| 117 | DevToConfig[i].iDriver = CurrentDriver; |
| 118 | |
| 119 | /* Fill in what we know, converting the driver name to lower case */ |
| 120 | DevToConfig[i].GDev.driver = xnfalloc(strlen(driver) + 1); |
| 121 | for (j = 0; (DevToConfig[i].GDev.driver[j] = tolower(driver[j])); j++); |
| 122 | |
| 123 | switch (bus) { |
| 124 | #ifdef XSERVER_LIBPCIACCESS |
| 125 | case BUS_PCI: |
| 126 | DevToConfig[i].pVideo = busData; |
| 127 | xf86PciConfigureNewDev(busData, DevToConfig[i].pVideo, |
| 128 | &DevToConfig[i].GDev, &chipset); |
| 129 | break; |
| 130 | #endif |
| 131 | #if (defined(__sparc__) || defined(__sparc)) && !defined(__OpenBSD__) |
| 132 | case BUS_SBUS: |
| 133 | DevToConfig[i].sVideo = busData; |
| 134 | xf86SbusConfigureNewDev(busData, DevToConfig[i].sVideo, |
| 135 | &DevToConfig[i].GDev); |
| 136 | break; |
| 137 | #endif |
| 138 | default: |
| 139 | break; |
| 140 | } |
| 141 | |
| 142 | /* Get driver's available options */ |
| 143 | if (xf86DriverList[CurrentDriver]->AvailableOptions) |
| 144 | DevToConfig[i].GDev.options = (OptionInfoPtr) |
| 145 | (*xf86DriverList[CurrentDriver]->AvailableOptions) (chipset, bus); |
| 146 | |
| 147 | return &DevToConfig[i].GDev; |
| 148 | |
| 149 | out: |
| 150 | return NULL; |
| 151 | } |
| 152 | |
| 153 | static XF86ConfInputPtr |
| 154 | configureInputSection(void) |
| 155 | { |
| 156 | XF86ConfInputPtr mouse = NULL; |
| 157 | |
| 158 | parsePrologue(XF86ConfInputPtr, XF86ConfInputRec) |
| 159 | |
| 160 | ptr->inp_identifier = "Keyboard0"; |
| 161 | ptr->inp_driver = "kbd"; |
| 162 | ptr->list.next = NULL; |
| 163 | |
| 164 | /* Crude mechanism to auto-detect mouse (os dependent) */ |
| 165 | { |
| 166 | int fd; |
| 167 | |
| 168 | fd = open(DFLT_MOUSE_DEV, 0); |
| 169 | if (fd != -1) { |
| 170 | foundMouse = TRUE; |
| 171 | close(fd); |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | mouse = calloc(1, sizeof(XF86ConfInputRec)); |
| 176 | mouse->inp_identifier = "Mouse0"; |
| 177 | mouse->inp_driver = "mouse"; |
| 178 | mouse->inp_option_lst = |
| 179 | xf86addNewOption(mouse->inp_option_lst, strdup("Protocol"), |
| 180 | strdup(DFLT_MOUSE_PROTO)); |
| 181 | mouse->inp_option_lst = |
| 182 | xf86addNewOption(mouse->inp_option_lst, strdup("Device"), |
| 183 | strdup(DFLT_MOUSE_DEV)); |
| 184 | mouse->inp_option_lst = |
| 185 | xf86addNewOption(mouse->inp_option_lst, strdup("ZAxisMapping"), |
| 186 | strdup("4 5 6 7")); |
| 187 | ptr = (XF86ConfInputPtr) xf86addListItem((glp) ptr, (glp) mouse); |
| 188 | return ptr; |
| 189 | } |
| 190 | |
| 191 | static XF86ConfScreenPtr |
| 192 | configureScreenSection(int screennum) |
| 193 | { |
| 194 | int i; |
| 195 | int depths[] = { 1, 4, 8, 15, 16, 24 /*, 32 */ }; |
| 196 | parsePrologue(XF86ConfScreenPtr, XF86ConfScreenRec) |
| 197 | |
| 198 | XNFasprintf(&ptr->scrn_identifier, "Screen%d", screennum); |
| 199 | XNFasprintf(&ptr->scrn_monitor_str, "Monitor%d", screennum); |
| 200 | XNFasprintf(&ptr->scrn_device_str, "Card%d", screennum); |
| 201 | |
| 202 | for (i = 0; i < sizeof(depths) / sizeof(depths[0]); i++) { |
| 203 | XF86ConfDisplayPtr display; |
| 204 | |
| 205 | display = calloc(1, sizeof(XF86ConfDisplayRec)); |
| 206 | display->disp_depth = depths[i]; |
| 207 | display->disp_black.red = display->disp_white.red = -1; |
| 208 | display->disp_black.green = display->disp_white.green = -1; |
| 209 | display->disp_black.blue = display->disp_white.blue = -1; |
| 210 | ptr->scrn_display_lst = (XF86ConfDisplayPtr) xf86addListItem((glp) ptr-> |
| 211 | scrn_display_lst, |
| 212 | (glp) |
| 213 | display); |
| 214 | } |
| 215 | |
| 216 | return ptr; |
| 217 | } |
| 218 | |
| 219 | static const char * |
| 220 | optionTypeToString(OptionValueType type) |
| 221 | { |
| 222 | switch (type) { |
| 223 | case OPTV_NONE: |
| 224 | return ""; |
| 225 | case OPTV_INTEGER: |
| 226 | return "<i>"; |
| 227 | case OPTV_STRING: |
| 228 | return "<str>"; |
| 229 | case OPTV_ANYSTR: |
| 230 | return "[<str>]"; |
| 231 | case OPTV_REAL: |
| 232 | return "<f>"; |
| 233 | case OPTV_BOOLEAN: |
| 234 | return "[<bool>]"; |
| 235 | case OPTV_FREQ: |
| 236 | return "<freq>"; |
| 237 | case OPTV_PERCENT: |
| 238 | return "<percent>"; |
| 239 | default: |
| 240 | return ""; |
| 241 | } |
| 242 | } |
| 243 | |
| 244 | static XF86ConfDevicePtr |
| 245 | configureDeviceSection(int screennum) |
| 246 | { |
| 247 | OptionInfoPtr p; |
| 248 | int i = 0; |
| 249 | |
| 250 | parsePrologue(XF86ConfDevicePtr, XF86ConfDeviceRec) |
| 251 | |
| 252 | /* Move device info to parser structure */ |
| 253 | if (asprintf(&ptr->dev_identifier, "Card%d", screennum) == -1) |
| 254 | ptr->dev_identifier = NULL; |
| 255 | ptr->dev_chipset = DevToConfig[screennum].GDev.chipset; |
| 256 | ptr->dev_busid = DevToConfig[screennum].GDev.busID; |
| 257 | ptr->dev_driver = DevToConfig[screennum].GDev.driver; |
| 258 | ptr->dev_ramdac = DevToConfig[screennum].GDev.ramdac; |
| 259 | for (i = 0; (i < MAXDACSPEEDS) && (i < CONF_MAXDACSPEEDS); i++) |
| 260 | ptr->dev_dacSpeeds[i] = DevToConfig[screennum].GDev.dacSpeeds[i]; |
| 261 | ptr->dev_videoram = DevToConfig[screennum].GDev.videoRam; |
| 262 | ptr->dev_textclockfreq = DevToConfig[screennum].GDev.textClockFreq; |
| 263 | ptr->dev_bios_base = DevToConfig[screennum].GDev.BiosBase; |
| 264 | ptr->dev_mem_base = DevToConfig[screennum].GDev.MemBase; |
| 265 | ptr->dev_io_base = DevToConfig[screennum].GDev.IOBase; |
| 266 | ptr->dev_clockchip = DevToConfig[screennum].GDev.clockchip; |
| 267 | for (i = 0; (i < MAXCLOCKS) && (i < DevToConfig[screennum].GDev.numclocks); |
| 268 | i++) |
| 269 | ptr->dev_clock[i] = DevToConfig[screennum].GDev.clock[i]; |
| 270 | ptr->dev_clocks = i; |
| 271 | ptr->dev_chipid = DevToConfig[screennum].GDev.chipID; |
| 272 | ptr->dev_chiprev = DevToConfig[screennum].GDev.chipRev; |
| 273 | ptr->dev_irq = DevToConfig[screennum].GDev.irq; |
| 274 | |
| 275 | /* Make sure older drivers don't segv */ |
| 276 | if (DevToConfig[screennum].GDev.options) { |
| 277 | /* Fill in the available driver options for people to use */ |
| 278 | const char *descrip = |
| 279 | " ### Available Driver options are:-\n" |
| 280 | " ### Values: <i>: integer, <f>: float, " |
| 281 | "<bool>: \"True\"/\"False\",\n" |
| 282 | " ### <string>: \"String\", <freq>: \"<f> Hz/kHz/MHz\",\n" |
| 283 | " ### <percent>: \"<f>%\"\n" |
| 284 | " ### [arg]: arg optional\n"; |
| 285 | ptr->dev_comment = strdup(descrip); |
| 286 | if (ptr->dev_comment) { |
| 287 | for (p = DevToConfig[screennum].GDev.options; p->name != NULL; p++) { |
| 288 | char *p_e; |
| 289 | const char *prefix = " #Option "; |
| 290 | const char *middle = " \t# "; |
| 291 | const char *suffix = "\n"; |
| 292 | const char *opttype = optionTypeToString(p->type); |
| 293 | char *optname; |
| 294 | int len = strlen(ptr->dev_comment) + strlen(prefix) + |
| 295 | strlen(middle) + strlen(suffix) + 1; |
| 296 | |
| 297 | if (asprintf(&optname, "\"%s\"", p->name) == -1) |
| 298 | break; |
| 299 | |
| 300 | len += max(20, strlen(optname)); |
| 301 | len += strlen(opttype); |
| 302 | |
| 303 | ptr->dev_comment = realloc(ptr->dev_comment, len); |
| 304 | if (!ptr->dev_comment) |
| 305 | break; |
| 306 | p_e = ptr->dev_comment + strlen(ptr->dev_comment); |
| 307 | sprintf(p_e, "%s%-20s%s%s%s", prefix, optname, middle, |
| 308 | opttype, suffix); |
| 309 | free(optname); |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | return ptr; |
| 315 | } |
| 316 | |
| 317 | static XF86ConfLayoutPtr |
| 318 | configureLayoutSection(void) |
| 319 | { |
| 320 | int scrnum = 0; |
| 321 | |
| 322 | parsePrologue(XF86ConfLayoutPtr, XF86ConfLayoutRec) |
| 323 | |
| 324 | ptr->lay_identifier = "X.org Configured"; |
| 325 | |
| 326 | { |
| 327 | XF86ConfInputrefPtr iptr; |
| 328 | |
| 329 | iptr = malloc(sizeof(XF86ConfInputrefRec)); |
| 330 | iptr->list.next = NULL; |
| 331 | iptr->iref_option_lst = NULL; |
| 332 | iptr->iref_inputdev_str = "Mouse0"; |
| 333 | iptr->iref_option_lst = |
| 334 | xf86addNewOption(iptr->iref_option_lst, strdup("CorePointer"), |
| 335 | NULL); |
| 336 | ptr->lay_input_lst = (XF86ConfInputrefPtr) |
| 337 | xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr); |
| 338 | } |
| 339 | |
| 340 | { |
| 341 | XF86ConfInputrefPtr iptr; |
| 342 | |
| 343 | iptr = malloc(sizeof(XF86ConfInputrefRec)); |
| 344 | iptr->list.next = NULL; |
| 345 | iptr->iref_option_lst = NULL; |
| 346 | iptr->iref_inputdev_str = "Keyboard0"; |
| 347 | iptr->iref_option_lst = |
| 348 | xf86addNewOption(iptr->iref_option_lst, strdup("CoreKeyboard"), |
| 349 | NULL); |
| 350 | ptr->lay_input_lst = (XF86ConfInputrefPtr) |
| 351 | xf86addListItem((glp) ptr->lay_input_lst, (glp) iptr); |
| 352 | } |
| 353 | |
| 354 | for (scrnum = 0; scrnum < nDevToConfig; scrnum++) { |
| 355 | XF86ConfAdjacencyPtr aptr; |
| 356 | |
| 357 | aptr = malloc(sizeof(XF86ConfAdjacencyRec)); |
| 358 | aptr->list.next = NULL; |
| 359 | aptr->adj_x = 0; |
| 360 | aptr->adj_y = 0; |
| 361 | aptr->adj_scrnum = scrnum; |
| 362 | XNFasprintf(&aptr->adj_screen_str, "Screen%d", scrnum); |
| 363 | if (scrnum == 0) { |
| 364 | aptr->adj_where = CONF_ADJ_ABSOLUTE; |
| 365 | aptr->adj_refscreen = NULL; |
| 366 | } |
| 367 | else { |
| 368 | aptr->adj_where = CONF_ADJ_RIGHTOF; |
| 369 | XNFasprintf(&aptr->adj_refscreen, "Screen%d", scrnum - 1); |
| 370 | } |
| 371 | ptr->lay_adjacency_lst = |
| 372 | (XF86ConfAdjacencyPtr) xf86addListItem((glp) ptr->lay_adjacency_lst, |
| 373 | (glp) aptr); |
| 374 | } |
| 375 | |
| 376 | return ptr; |
| 377 | } |
| 378 | |
| 379 | static XF86ConfFlagsPtr |
| 380 | configureFlagsSection(void) |
| 381 | { |
| 382 | parsePrologue(XF86ConfFlagsPtr, XF86ConfFlagsRec) |
| 383 | |
| 384 | return ptr; |
| 385 | } |
| 386 | |
| 387 | static XF86ConfModulePtr |
| 388 | configureModuleSection(void) |
| 389 | { |
| 390 | char **elist, **el; |
| 391 | |
| 392 | /* Find the list of extension & font modules. */ |
| 393 | const char *esubdirs[] = { |
| 394 | "extensions", |
| 395 | "fonts", |
| 396 | NULL |
| 397 | }; |
| 398 | parsePrologue(XF86ConfModulePtr, XF86ConfModuleRec) |
| 399 | |
| 400 | elist = LoaderListDirs(esubdirs, NULL); |
| 401 | if (elist) { |
| 402 | for (el = elist; *el; el++) { |
| 403 | XF86LoadPtr module; |
| 404 | |
| 405 | module = calloc(1, sizeof(XF86LoadRec)); |
| 406 | module->load_name = *el; |
| 407 | ptr->mod_load_lst = (XF86LoadPtr) xf86addListItem((glp) ptr-> |
| 408 | mod_load_lst, |
| 409 | (glp) module); |
| 410 | } |
| 411 | free(elist); |
| 412 | } |
| 413 | |
| 414 | return ptr; |
| 415 | } |
| 416 | |
| 417 | static XF86ConfFilesPtr |
| 418 | configureFilesSection(void) |
| 419 | { |
| 420 | parsePrologue(XF86ConfFilesPtr, XF86ConfFilesRec) |
| 421 | |
| 422 | if (xf86ModulePath) |
| 423 | ptr->file_modulepath = strdup(xf86ModulePath); |
| 424 | if (defaultFontPath) |
| 425 | ptr->file_fontpath = strdup(defaultFontPath); |
| 426 | |
| 427 | return ptr; |
| 428 | } |
| 429 | |
| 430 | static XF86ConfMonitorPtr |
| 431 | configureMonitorSection(int screennum) |
| 432 | { |
| 433 | parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec) |
| 434 | |
| 435 | XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum); |
| 436 | ptr->mon_vendor = strdup("Monitor Vendor"); |
| 437 | ptr->mon_modelname = strdup("Monitor Model"); |
| 438 | |
| 439 | return ptr; |
| 440 | } |
| 441 | |
| 442 | /* Initialize Configure Monitor from Detailed Timing Block */ |
| 443 | static void |
| 444 | handle_detailed_input(struct detailed_monitor_section *det_mon, void *data) |
| 445 | { |
| 446 | XF86ConfMonitorPtr ptr = (XF86ConfMonitorPtr) data; |
| 447 | |
| 448 | switch (det_mon->type) { |
| 449 | case DS_NAME: |
| 450 | ptr->mon_modelname = realloc(ptr->mon_modelname, |
| 451 | strlen((char *) (det_mon->section.name)) + |
| 452 | 1); |
| 453 | strcpy(ptr->mon_modelname, (char *) (det_mon->section.name)); |
| 454 | break; |
| 455 | case DS_RANGES: |
| 456 | ptr->mon_hsync[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_h; |
| 457 | ptr->mon_hsync[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_h; |
| 458 | ptr->mon_n_vrefresh = 1; |
| 459 | ptr->mon_vrefresh[ptr->mon_n_hsync].lo = det_mon->section.ranges.min_v; |
| 460 | ptr->mon_vrefresh[ptr->mon_n_hsync].hi = det_mon->section.ranges.max_v; |
| 461 | ptr->mon_n_hsync++; |
| 462 | default: |
| 463 | break; |
| 464 | } |
| 465 | } |
| 466 | |
| 467 | static XF86ConfMonitorPtr |
| 468 | configureDDCMonitorSection(int screennum) |
| 469 | { |
| 470 | int len, mon_width, mon_height; |
| 471 | |
| 472 | #define displaySizeMaxLen 80 |
| 473 | char displaySize_string[displaySizeMaxLen]; |
| 474 | int displaySizeLen; |
| 475 | |
| 476 | parsePrologue(XF86ConfMonitorPtr, XF86ConfMonitorRec) |
| 477 | |
| 478 | XNFasprintf(&ptr->mon_identifier, "Monitor%d", screennum); |
| 479 | ptr->mon_vendor = strdup(ConfiguredMonitor->vendor.name); |
| 480 | XNFasprintf(&ptr->mon_modelname, "%x", ConfiguredMonitor->vendor.prod_id); |
| 481 | |
| 482 | /* features in centimetres, we want millimetres */ |
| 483 | mon_width = 10 * ConfiguredMonitor->features.hsize; |
| 484 | mon_height = 10 * ConfiguredMonitor->features.vsize; |
| 485 | |
| 486 | #ifdef CONFIGURE_DISPLAYSIZE |
| 487 | ptr->mon_width = mon_width; |
| 488 | ptr->mon_height = mon_height; |
| 489 | #else |
| 490 | if (mon_width && mon_height) { |
| 491 | /* when values available add DisplaySize option AS A COMMENT */ |
| 492 | |
| 493 | displaySizeLen = snprintf(displaySize_string, displaySizeMaxLen, |
| 494 | "\t#DisplaySize\t%5d %5d\t# mm\n", |
| 495 | mon_width, mon_height); |
| 496 | |
| 497 | if (displaySizeLen > 0 && displaySizeLen < displaySizeMaxLen) { |
| 498 | if (ptr->mon_comment) { |
| 499 | len = strlen(ptr->mon_comment); |
| 500 | } |
| 501 | else { |
| 502 | len = 0; |
| 503 | } |
| 504 | if ((ptr->mon_comment = |
| 505 | realloc(ptr->mon_comment, |
| 506 | len + strlen(displaySize_string) + 1))) { |
| 507 | strcpy(ptr->mon_comment + len, displaySize_string); |
| 508 | } |
| 509 | } |
| 510 | } |
| 511 | #endif /* def CONFIGURE_DISPLAYSIZE */ |
| 512 | |
| 513 | xf86ForEachDetailedBlock(ConfiguredMonitor, handle_detailed_input, ptr); |
| 514 | |
| 515 | if (ConfiguredMonitor->features.dpms) { |
| 516 | ptr->mon_option_lst = |
| 517 | xf86addNewOption(ptr->mon_option_lst, strdup("DPMS"), NULL); |
| 518 | } |
| 519 | |
| 520 | return ptr; |
| 521 | } |
| 522 | |
| 523 | void |
| 524 | DoConfigure(void) |
| 525 | { |
| 526 | int i, j, screennum = -1; |
| 527 | const char *home = NULL; |
| 528 | char filename[PATH_MAX]; |
| 529 | const char *addslash = ""; |
| 530 | XF86ConfigPtr xf86config = NULL; |
| 531 | char **vlist, **vl; |
| 532 | int *dev2screen; |
| 533 | |
| 534 | vlist = xf86DriverlistFromCompile(); |
| 535 | |
| 536 | if (!vlist) { |
| 537 | ErrorF("Missing output drivers. Configuration failed.\n"); |
| 538 | goto bail; |
| 539 | } |
| 540 | |
| 541 | ErrorF("List of video drivers:\n"); |
| 542 | for (vl = vlist; *vl; vl++) |
| 543 | ErrorF("\t%s\n", *vl); |
| 544 | |
| 545 | /* Load all the drivers that were found. */ |
| 546 | xf86LoadModules(vlist, NULL); |
| 547 | |
| 548 | free(vlist); |
| 549 | |
| 550 | xorgHWAccess = xf86EnableIO(); |
| 551 | |
| 552 | /* Create XF86Config file structure */ |
| 553 | xf86config = calloc(1, sizeof(XF86ConfigRec)); |
| 554 | |
| 555 | /* Call all of the probe functions, reporting the results. */ |
| 556 | for (CurrentDriver = 0; CurrentDriver < xf86NumDrivers; CurrentDriver++) { |
| 557 | Bool found_screen; |
| 558 | DriverRec *const drv = xf86DriverList[CurrentDriver]; |
| 559 | |
| 560 | found_screen = xf86CallDriverProbe(drv, TRUE); |
| 561 | if (found_screen && drv->Identify) { |
| 562 | (*drv->Identify) (0); |
| 563 | } |
| 564 | } |
| 565 | |
| 566 | if (nDevToConfig <= 0) { |
| 567 | ErrorF("No devices to configure. Configuration failed.\n"); |
| 568 | goto bail; |
| 569 | } |
| 570 | |
| 571 | /* Add device, monitor and screen sections for detected devices */ |
| 572 | for (screennum = 0; screennum < nDevToConfig; screennum++) { |
| 573 | XF86ConfDevicePtr DevicePtr; |
| 574 | XF86ConfMonitorPtr MonitorPtr; |
| 575 | XF86ConfScreenPtr ScreenPtr; |
| 576 | |
| 577 | DevicePtr = configureDeviceSection(screennum); |
| 578 | xf86config->conf_device_lst = (XF86ConfDevicePtr) xf86addListItem((glp) |
| 579 | xf86config-> |
| 580 | conf_device_lst, |
| 581 | (glp) |
| 582 | DevicePtr); |
| 583 | MonitorPtr = configureMonitorSection(screennum); |
| 584 | xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) MonitorPtr); |
| 585 | ScreenPtr = configureScreenSection(screennum); |
| 586 | xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp) |
| 587 | xf86config-> |
| 588 | conf_screen_lst, |
| 589 | (glp) |
| 590 | ScreenPtr); |
| 591 | } |
| 592 | |
| 593 | xf86config->conf_files = configureFilesSection(); |
| 594 | xf86config->conf_modules = configureModuleSection(); |
| 595 | xf86config->conf_flags = configureFlagsSection(); |
| 596 | xf86config->conf_videoadaptor_lst = NULL; |
| 597 | xf86config->conf_modes_lst = NULL; |
| 598 | xf86config->conf_vendor_lst = NULL; |
| 599 | xf86config->conf_dri = NULL; |
| 600 | xf86config->conf_input_lst = configureInputSection(); |
| 601 | xf86config->conf_layout_lst = configureLayoutSection(); |
| 602 | |
| 603 | home = getenv("HOME"); |
| 604 | if ((home == NULL) || (home[0] == '\0')) { |
| 605 | home = "/"; |
| 606 | } |
| 607 | else { |
| 608 | /* Determine if trailing slash is present or needed */ |
| 609 | int l = strlen(home); |
| 610 | |
| 611 | if (home[l - 1] != '/') { |
| 612 | addslash = "/"; |
| 613 | } |
| 614 | } |
| 615 | |
| 616 | snprintf(filename, sizeof(filename), "%s%s" XF86CONFIGFILE ".new", |
| 617 | home, addslash); |
| 618 | |
| 619 | if (xf86writeConfigFile(filename, xf86config) == 0) { |
| 620 | xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", |
| 621 | filename, strerror(errno)); |
| 622 | goto bail; |
| 623 | } |
| 624 | |
| 625 | xf86DoConfigurePass1 = FALSE; |
| 626 | /* Try to get DDC information filled in */ |
| 627 | xf86ConfigFile = filename; |
| 628 | if (xf86HandleConfigFile(FALSE) != CONFIG_OK) { |
| 629 | goto bail; |
| 630 | } |
| 631 | |
| 632 | xf86DoConfigurePass1 = FALSE; |
| 633 | |
| 634 | dev2screen = xnfcalloc(1, xf86NumDrivers * sizeof(int)); |
| 635 | |
| 636 | { |
| 637 | Bool *driverProbed = xnfcalloc(1, xf86NumDrivers * sizeof(Bool)); |
| 638 | |
| 639 | for (screennum = 0; screennum < nDevToConfig; screennum++) { |
| 640 | int k, l, n, oldNumScreens; |
| 641 | |
| 642 | i = DevToConfig[screennum].iDriver; |
| 643 | |
| 644 | if (driverProbed[i]) |
| 645 | continue; |
| 646 | driverProbed[i] = TRUE; |
| 647 | |
| 648 | oldNumScreens = xf86NumScreens; |
| 649 | |
| 650 | xf86CallDriverProbe(xf86DriverList[i], FALSE); |
| 651 | |
| 652 | /* reorder */ |
| 653 | k = screennum > 0 ? screennum : 1; |
| 654 | for (l = oldNumScreens; l < xf86NumScreens; l++) { |
| 655 | /* is screen primary? */ |
| 656 | Bool primary = FALSE; |
| 657 | |
| 658 | for (n = 0; n < xf86Screens[l]->numEntities; n++) { |
| 659 | if (xf86IsEntityPrimary(xf86Screens[l]->entityList[n])) { |
| 660 | dev2screen[0] = l; |
| 661 | primary = TRUE; |
| 662 | break; |
| 663 | } |
| 664 | } |
| 665 | if (primary) |
| 666 | continue; |
| 667 | /* not primary: assign it to next device of same driver */ |
| 668 | /* |
| 669 | * NOTE: we assume that devices in DevToConfig |
| 670 | * and xf86Screens[] have the same order except |
| 671 | * for the primary device which always comes first. |
| 672 | */ |
| 673 | for (; k < nDevToConfig; k++) { |
| 674 | if (DevToConfig[k].iDriver == i) { |
| 675 | dev2screen[k++] = l; |
| 676 | break; |
| 677 | } |
| 678 | } |
| 679 | } |
| 680 | } |
| 681 | free(driverProbed); |
| 682 | } |
| 683 | |
| 684 | if (nDevToConfig != xf86NumScreens) { |
| 685 | ErrorF("Number of created screens does not match number of detected" |
| 686 | " devices.\n Configuration failed.\n"); |
| 687 | goto bail; |
| 688 | } |
| 689 | |
| 690 | xf86PostProbe(); |
| 691 | |
| 692 | for (j = 0; j < xf86NumScreens; j++) { |
| 693 | xf86Screens[j]->scrnIndex = j; |
| 694 | } |
| 695 | |
| 696 | xf86freeMonitorList(xf86config->conf_monitor_lst); |
| 697 | xf86config->conf_monitor_lst = NULL; |
| 698 | xf86freeScreenList(xf86config->conf_screen_lst); |
| 699 | xf86config->conf_screen_lst = NULL; |
| 700 | for (j = 0; j < xf86NumScreens; j++) { |
| 701 | XF86ConfMonitorPtr MonitorPtr; |
| 702 | XF86ConfScreenPtr ScreenPtr; |
| 703 | |
| 704 | ConfiguredMonitor = NULL; |
| 705 | |
| 706 | if ((*xf86Screens[dev2screen[j]]->PreInit) (xf86Screens[dev2screen[j]], |
| 707 | PROBE_DETECT) && |
| 708 | ConfiguredMonitor) { |
| 709 | MonitorPtr = configureDDCMonitorSection(j); |
| 710 | } |
| 711 | else { |
| 712 | MonitorPtr = configureMonitorSection(j); |
| 713 | } |
| 714 | ScreenPtr = configureScreenSection(j); |
| 715 | |
| 716 | xf86config->conf_monitor_lst = (XF86ConfMonitorPtr) xf86addListItem((glp) xf86config->conf_monitor_lst, (glp) MonitorPtr); |
| 717 | xf86config->conf_screen_lst = (XF86ConfScreenPtr) xf86addListItem((glp) |
| 718 | xf86config-> |
| 719 | conf_screen_lst, |
| 720 | (glp) |
| 721 | ScreenPtr); |
| 722 | } |
| 723 | |
| 724 | if (xf86writeConfigFile(filename, xf86config) == 0) { |
| 725 | xf86Msg(X_ERROR, "Unable to write config file: \"%s\": %s\n", |
| 726 | filename, strerror(errno)); |
| 727 | goto bail; |
| 728 | } |
| 729 | |
| 730 | ErrorF("\n"); |
| 731 | |
| 732 | if (!foundMouse) { |
| 733 | ErrorF("\n" __XSERVERNAME__ " is not able to detect your mouse.\n" |
| 734 | "Edit the file and correct the Device.\n"); |
| 735 | } |
| 736 | else { |
| 737 | ErrorF("\n" __XSERVERNAME__ " detected your mouse at device %s.\n" |
| 738 | "Please check your config if the mouse is still not\n" |
| 739 | "operational, as by default " __XSERVERNAME__ |
| 740 | " tries to autodetect\n" "the protocol.\n", DFLT_MOUSE_DEV); |
| 741 | } |
| 742 | |
| 743 | if (xf86NumScreens > 1) { |
| 744 | ErrorF("\n" __XSERVERNAME__ |
| 745 | " has configured a multihead system, please check your config.\n"); |
| 746 | } |
| 747 | |
| 748 | ErrorF("\nYour %s file is %s\n\n", XF86CONFIGFILE, filename); |
| 749 | ErrorF("To test the server, run 'X -config %s'\n\n", filename); |
| 750 | |
| 751 | bail: |
| 752 | OsCleanup(TRUE); |
| 753 | AbortDDX(EXIT_ERR_CONFIGURE); |
| 754 | fflush(stderr); |
| 755 | exit(0); |
| 756 | } |
| 757 | |
| 758 | /* Xorg -showopts: |
| 759 | * For each driver module installed, print out the list |
| 760 | * of options and their argument types, then exit |
| 761 | * |
| 762 | * Author: Marcus Schaefer, ms@suse.de |
| 763 | */ |
| 764 | |
| 765 | void |
| 766 | DoShowOptions(void) |
| 767 | { |
| 768 | int i = 0; |
| 769 | char **vlist = 0; |
| 770 | char *pSymbol = 0; |
| 771 | XF86ModuleData *initData = 0; |
| 772 | |
| 773 | if (!(vlist = xf86DriverlistFromCompile())) { |
| 774 | ErrorF("Missing output drivers\n"); |
| 775 | goto bail; |
| 776 | } |
| 777 | xf86LoadModules(vlist, 0); |
| 778 | free(vlist); |
| 779 | for (i = 0; i < xf86NumDrivers; i++) { |
| 780 | if (xf86DriverList[i]->AvailableOptions) { |
| 781 | const OptionInfoRec *pOption = |
| 782 | (*xf86DriverList[i]->AvailableOptions) (0, 0); |
| 783 | if (!pOption) { |
| 784 | ErrorF("(EE) Couldn't read option table for %s driver\n", |
| 785 | xf86DriverList[i]->driverName); |
| 786 | continue; |
| 787 | } |
| 788 | XNFasprintf(&pSymbol, "%sModuleData", |
| 789 | xf86DriverList[i]->driverName); |
| 790 | initData = LoaderSymbol(pSymbol); |
| 791 | if (initData) { |
| 792 | XF86ModuleVersionInfo *vers = initData->vers; |
| 793 | const OptionInfoRec *p; |
| 794 | |
| 795 | ErrorF("Driver[%d]:%s[%s] {\n", |
| 796 | i, xf86DriverList[i]->driverName, vers->vendor); |
| 797 | for (p = pOption; p->name != NULL; p++) { |
| 798 | ErrorF("\t%s:%s\n", p->name, optionTypeToString(p->type)); |
| 799 | } |
| 800 | ErrorF("}\n"); |
| 801 | } |
| 802 | } |
| 803 | } |
| 804 | bail: |
| 805 | OsCleanup(TRUE); |
| 806 | AbortDDX(EXIT_ERR_DRIVERS); |
| 807 | fflush(stderr); |
| 808 | exit(0); |
| 809 | } |