/*
*
* 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,
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) 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.
*/
/*
* fbc_res - Video modes/resolutions (-res option)
*/
#include <ctype.h> /* isdigit(), ispunct(), toupper() */
#include <stdio.h> /* fputc(), printf(), sprintf() */
#include <string.h> /* str[case]cmp(), strrchr(), strstr(), ... */
#include "xf86Parser.h" /* Public function, etc. declarations */
#include "resolutions.h" /* Video mode summary table: SunVideoTable[] */
#include "sun_edid.h" /* EDID data parsing */
#include "fbc.h" /* Common fbconf_xorg(1M) definitions */
#include "fbc_xorg.h" /* Edit config file data representations */
#include "fbc_ask.h" /* User interaction */
#include "fbc_dev.h" /* Identify the graphics device (-dev opt) */
#include "fbc_error.h" /* Error reporting */
#include "fbc_mode_list.h" /* List of Modes from the config file */
#include "fbc_properties.h" /* fbconf_xorg(1M) program properties */
#include "fbc_res.h" /* Video modes/resolutions (-res option) */
#include "fbc_res_compatible.h" /* Video mode compatibity check (-res) */
/*
* fbc_resname_attr_str()
*
* Return TRUE iff the video mode/resolution name contains a case
* insensitive version of the specified attribute substring (e.g.,
* "STEREO"), set off by punctuation characters (typically '_' or
*
* This code doesn't observe XFree86 name comparison rules with
* respect to whitespace and underscores.
*/
static
int
const char *resname, /* Video mode/resolution name */
const char *attribute) /* Attribute substring */
{
for (resname_ptr = resname;
resname_ptr += 1) {
== 0)) {
return (TRUE);
}
}
prev_char = *resname_ptr;
}
return (FALSE);
} /* fbc_resname_attr_str() */
/*
* fbc_resname_attr_chr()
*
* Return TRUE iff the mode/resolution name has a case-insensitive
* version of the specified suffix character. The suffix character
* must be passed to this function in upper case.
*
* This code doesn't observe XFree86 comparison rules w/r/t
* whitespace and underscores.
*/
static
int
const char *resname, /* Video mode name */
char attribute) /* Attribute suffix char, upper case */
{
} /* fbc_resname_attr_chr() */
/*
* fbc_resname_stereo()
*
* Return TRUE iff the mode/resolution name indicates stereo video
* mode. Such names contain a "STEREO" substring or have an 'S' or
* 's' suffix character.
*/
int
const char *resname) /* Video mode name */
{
} /* fbc_resname_stereo() */
/*
* fbc_resname_digital()
*
* Return TRUE iff the mode/resolution name indicates digital video
* mode. Such names contain a "DIG" substring.
*/
int
const char *resname) /* Video mode/resolution name */
{
} /* fbc_resname_digital() */
/*
* fbc_resname_cmp()
*
* Compare two video mode/resolution name strings for equivalence.
* The first name, full_resname, is the full name of a valid
* mode/resolution. The name to be validated, resname, matches
* the first name if it is identical or if it is a substring
* consisting of the numeric dimensions and anything that follows in
* the full name.
*
* Assumptions made by this algorithm:
* * Abbreviations begin with the first digit of the dimensions.
* * A full name can not be abbreviated unless it contains an
* underscore (_).
* * Its abbreviation would be the entire substring following the
* last underscore.
* * XFree86 comparison rules concerning whitespace and
* underscores are not applied. The alternative would
* involve calling xf86nameCompare() instead of strcasecmp().
*
* Return zero iff the video mode/resolution names match.
*/
static
int
const char *full_resname, /* Full name of a video mode/res */
{
return (0); /* Exact match of full names */
}
}
}
return (1); /* No match */
} /* fbc_resname_cmp() */
/*
* fbc_get_monitor_id()
*
* If there is more than one video stream, return a string containing
* the stream number (" %d"). Otherwise return an empty string ("").
* The string is returned in a monitor_id_buf[FBC_MAX_MONITOR_ID_LEN]
* buffer, and will be used to identify the monitor for display
* purposes (i.e., "... monitor <id> ..." or just "... monitor ...").
*/
void
int stream_index, /* Video stream index (zero-based) */
char *monitor_id_buf) /* Returned monitor ID, else "" */
{
*monitor_id_buf = '\0';
}
} /* fbc_get_monitor_id() */
/*
* fbc_in_edid_modes()
*
* Given a video mode name from the config file, find out whether:
* * the video mode name is present in the list of modes (from
* EDID) that are supported by the display device
* * the video mode name is first in the list (e.g. represents the
* preferred mode/resolution for the display)
*
* Return the zero-relative subscript of the video mode name within
* the list/array of mode/resolution names. Return
* FBC_NOT_IN_EDID_MODES if the name is not present in the list.
*/
static
int
const char *mode_name) /* Video mode name */
{
int i; /* Index of matching EDID mode name */
// ??? Accept abbreviations, etc. ...
== 0) {
// ??? ... or not
// ??? if (strcasecmp(edid_mode[i].name, mode_name) == 0) {
return (i);
}
}
}
return (FBC_NOT_IN_EDID_MODES); /* No list or name isn't in list */
} /* fbc_in_edid_modes() */
/*
* fbc_list_video_mode()
*
* Display the specified video mode name from the config file unless
* it's disqualified by some special case. This typically is a video
* mode name that has been referenced by the active Monitor section
* of the config file.
*
* Set footnote[0] to TRUE iff a video mode is displayed that is not
* supported by all display devices.
*
* Display any applicable footnote references (e.g. [1], [2], ...).
* Footnotes are applicable iff the video mode name appears in the
* list of EDID timings supported by the display device. Return the
* corresponding note text, to be displayed later by the caller.
*/
static
void
const char *mode_name, /* Video mode name to display */
int support_level, /* FBC_xxxxx_EDID_MODEx */
int footnote[]) /* Returned flags, else unchanged */
{
int i; /* Index of matching video mode name */
/*
* Suppress certain video mode names
*
??? Is this code suitable for kfb? For any other frame buffers?
* 'I' - Interlaced video timing
* 'S' - Stereo video mode
*/
return;
}
/*
* Display this video mode name
*/
/*
* For the indicated video streams (-dev), display any footnote numbers
*/
stream_index += 1) {
/*
* See whether video mode is supported by this display device
*
* Most video modes should be looked up in the
* support level footnotes for "AUTO" or "NONE" is
* the exception.
*/
i = support_level;
if (support_level == FBC_CHECK_EDID_MODES) {
i = fbc_in_edid_modes(
}
if (i == FBC_NOT_IN_EDID_MODES) {
} else {
/*
* Show the whether the video mode is supported
*/
if (i == FBC_FIRST_EDID_MODE) {
/* First mode in list is preferred one */
}
}
}
/*
* Terminate the line containing the video mode and any note numbers
*/
putchar('\n');
} /* fbc_list_video_mode() */
/*
* Keywords representing the display device's preferred video mode
*/
static const char *mode_pref_keywd[] = {
FBC_RESNAME_PREFERRED, /* AUTO */
FBC_RESNAME_NONE, /* NONE */
NULL /* End marker */
};
/*
* fbc_res_list_modes()
*
* Display the video mode names from the active Monitor section
* (-res ?). For each video mode and for each video stream, footnote
* whether the mode is supported by the stream's display device and
* whether it is the preferred mode for the display device.
*
* Note that a mode name should not be displayed unless the config
* file contains the a ModeLine or Mode-EndMode entry to define that
* mode. Only the "mode_list" modes are defined in the config file.
* Additional modes in the edid_res_info[].mode_names arrays and in
* the SunVideoTable[] array are not defined in the config file.
*/
void
{
int i; /* Loop counter / array index */
/*
* No footnotes to display yet
*/
for (i = 0; i <= FBC_MAX_NOTES; i += 1) {
}
printf("Video modes accepted by the -res option:\n");
/*
* Display keywords representing the monitor's preferred video mode
*
* The FBC_FIRST_EDID_MODE argument is used here in order to
* force the generation of the desired "supports" and
* "preferred" footnotes.
*/
mode_pref_keywd[i], /* "AUTO", "NONE" */
FBC_FIRST_EDID_MODE, /* Preferred */
edid_res_info, /* Not used */
footnote);
}
/*
* Get from the config file the video modes to be displayed
*/
/*
* Get the supported video modes from the EDID data
*/
/*
* Exclude any mode that's incompatible w/ this frame buffer & monitor
*/
/*
* Display the video modes that are configured for this frame buffer
*/
continue; /* This video mode has been excluded */
}
footnote);
}
/*
* Display all footnotes that apply
*/
stream_index += 1) {
int note_num;
printf("[%d] Resolution is supported by monitor%s\n",
}
note_num += 1;
printf("[%d] Preferred resolution for monitor%s\n",
}
"No EDID data for monitor%s. Can not determine supported resolutions.\n",
}
}
if (footnoted) {
}
if (footnote[0]) {
"Use of an unsupported resolution can render the video display unusable.\n\n");
}
printf("Abbreviations such as \"1280x1024x75\" may also be used.\n");
/*
* Release dynamically allocated memory
*/
stream_index += 1) {
}
} /* fbc_res_list_modes() */
/*
* fbc_is_known_mode()
*
* Given a "-res <video_mode> ..." command line option:
* * If present in the video mode name, replace '@' with 'x'
* * Look up the video mode name in these places:
* * The EDID video mode names supported by the monitor
* * The active Monitor section of the configuration file
* * The built-in SunVideoTable[] array
* * If the video mode name is found, substitute and return its
* canonical form (full spelling, in the proper case, with no '@'
* character)
* * Return video mode display dimensions or something like them
* Return TRUE iff the video mode name is found.
*/
static
int
char *mode_name_buf, /* Video mode name scratch buffer */
{
/*
* Try to determine the display parameters for this video mode
*
* For example, "VESA_STD_1280x1024x60" or "1280x1024x60"
* would yeild 1280 for width and 1024 for height.
*
* This is being done to cover the case in which the video
* mode name isn't recognized. The values may be needed for
* "-res <video_mode> try" support.
*
* This approach wouldn't work well with "AUTO" or "NONE."
* It also is questionable to assume that a video mode name
* reflects precise values. Note the height values for these
* EDID Standard Timings and the corresponding video mode
* names:
* 1152x921x76 => "SUNW_STD_1152x900x76"
* 1152x921x66 => "SUNW_STD_1152x900x66"
*/
ptr += 1;
} else {
}
< 2) {
video_mode->width = 0;
video_mode->height = 0;
}
/*
* If found, replace '@' with 'x' (e.g. "640x480@60" => "640x480x60")
*/
>= mode_name_buf_len) {
return (FALSE); /* Mode name is too problematic */
}
}
/*
* See whether the video mode name is found among the EDID modes
*
* Ideally, the video mode name can be found with each of the
* specified video streams, since we'll have to reject it
* later otherwise. For now, however, we just want to know
* whether the name is valid.
*/
stream_index += 1) {
continue; /* No EDID data, etc. */
}
edid_mode += 1) {
== 0) {
/* Return w/ canonicalized name, etc. */
return (strlcpy(mode_name_buf,
}
}
}
/*
* See whether the video mode name is found in the config file
*/
/* Return succesfully w/ canonicalized name, etc. */
return (TRUE);
}
}
/*
* See whether the video mode name is found in the built-in table
*/
/* Return succesfully w/ canonicalized name, etc. */
return (TRUE);
}
}
/*
* Unrecognized video mode name
*/
return (FALSE);
} /* fbc_is_known_mode() */
/*
* fbc_is_supported_mode()
*
* Given the canonicalized video mode name derived from a
* "-res <video_mode> ..." command line option:
* * Make sure the video mode is supported by all of the display
* devices associated with the frame buffer device. The EDID
* data from each display device says which video timings and
* therefore which names are supported.
* * Make sure the hardware combination of frame buffer and each
* display device works with this video mode.
* Return TRUE iff the video mode appears valid.
*/
static
int
const char *mode_name, /* Video mode name (-res) */
{
#if (1) /* Unexplained vestige from Xsun's kfbconfig.c and nfbconfig.c */
/*
* Compensate for some omission in sun_edid.c or resolutions.c?
*/
mode_name = "1600x1200x60";
}
#endif
#if (0) /* Is this a worthwhile check? */
/*
* Make sure the mode is defined by a ModeLine / Mode-EndMode entry
*/
"Mode \"%s\" not found using Monitor section \"%s\"\n",
return (FBC_ERR_GENERAL);
}
#endif
/*
* Validate the video mode for the indicated video streams (-dev)
*/
stream_index += 1) {
/*
* Make sure this monitor provided EDID data
*/
"Warning: EDID data is not available for monitor%s\n",
continue; /* Check any other monitors too */
}
/*
* See if this monitor supports the mode, according to EDID
*/
for ( ; ; edid_mode += 1) {
break; /* Not supported by this monitor */
}
break; /* Supported by this monitor */
}
}
}
return (supported_mode);
} /* fbc_is_supported_mode() */
/*
* fbc_res_validate_mode()
*
* Given a "-res <video_mode> [nocheck|noconfirm] ..." command line
* option:
* * Look up the video mode name argument in these places:
* * The predefined keywords, "AUTO" and "NONE"
* * The EDID video mode names supported by the monitor
* * The active Monitor section of the configuration file
* * The built-in SunVideoTable[] array
* * If the video mode name is found, and if necessary, substitute
* and return its canonical form.
* * If the user didn't specify "nocheck" or "noconfirm",
* * make sure the video mode name was found, and
* * make sure the video mode is supported by each of the
* applicable display devices, including in combination
* with the frame buffer, or else
* * ask if the user knows what he's doing.
* Return TRUE iff the video mode appears valid or if the user
* insists.
*/
int
char mode_name_buf[], /* Returned canonicalized mode name */
{
int i; /* Loop counter / array index */
/*
* Get the video modes from the active Monitor sectn of the config file
*/
/*
* Get the video modes from the EDID data for each display device
*/
/*
* Free the list of video modes from the config file
*
* Note that this is an unintrusive list. Freeing it does
* not affect the xf86 config data structures.
*/
/*
* Accept a keyword representing the monitors' preferred video mode
*
??? * TODO: Make sure all display devices have the same preferred mode
*/
/*
* Return succesfully w/ preferred video mode, "AUTO"
*/
}
for ( ;
stream_index += 1) {
}
/*
* If "AUTO" or "NONE" is specified, there is no need
* to include a SunModes section. So remove it,
* both internal & external representation
*/
/*
* Also remove the device specific use SunModes entry as well
*/
return (TRUE);
}
}
/*
* Look up and canonicalize the -res <video_mode> name argument
*/
/*
* Check the video mode unless the user said "nocheck"
*/
valid_mode = TRUE;
/*
* Accept this video mode if either main bullet point is true:
*
* * The video mode satisfies all of:
* * is known from EDID, the config file, etc.
* * is supported by the display device(s)
* combination
* * The user said "noconfirm" or gives confirmation
*/
valid_mode = FALSE;
msg_format = "Unrecognized video mode, \"%s\"\n";
if (known_mode) {
"Cannot verify that \"%s\" is a supported video mode\n";
/*
* See if frame buf & monitor(s) like this mode
*/
"Hardware does not support video mode, \"%s\"\n";
if (fbc_res_compatible(device,
NULL)) {
valid_mode = TRUE;
}
}
}
if (!valid_mode) {
fbc_ask_yes_no("Use \"%s\" anyway (yes/no) ? ",
video_mode->name);
}
if (!valid_mode) {
fbc_errormsg("No configuration changes made!\n");
"Note: Use \"-res ?\" to show valid video modes\n");
}
}
/*
* Discard the mode name lists derived from EDID data
*/
stream_index += 1) {
}
/*
* after the validation, only keep the specified sun mode in the
* SunModes section
*/
/*
* remove the SunModes external representation that was added when
* the config file was read.
* A device specific SunModes section will be added to the file
* later which only includes the mode specified in the -res option.
* The reason is if all the SunModes are included in the mode section,
* xf86ValidateModes code will set the virtual dimension to the largest
* possible. This is not what is expected from fbconfig.
*/
if (!sun_mode) {
/*
* if the specified mode is not a SunMode, remove the
* use SunMode entry
*/
}
return (valid_mode);
} /* fbc_res_validate_mode() */
/* End of fbc_res.c */