/*
*
* 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_dev - Identify the graphics device (-dev opt)
*/
#include <ctype.h> /* isdigit() */
#include <errno.h> /* errno */
#include <stdlib.h> /* strchr(), strtol() */
#include <string.h> /* memset(), strcasecmp(), strerror(), ... */
#include <unistd.h> /* readlink() */
#include "fbc.h" /* Common fbconf_xorg(1M) definitions */
#include "fbc_error.h" /* Error reporting */
#include "fbc_dev.h" /* Identify the graphics device (-dev opt) */
#include "fbc_open_device.h" /* Open the frame buffer device */
/*
* fbc_get_device_arg()
*
* Scan the fbconf_xorg(1M) program command line options in order to
* find the (first) frame buffer device name (-dev) argument, if any.
* Return a pointer to the -dev argument string, else a NULL pointer.
*
* Considerations:
* * The -dev option must be fully spelled out, not abbreviated.
* Until the device type is known, we don't know what other
* command line options might be supported. At least one of
* -defaults, -defdepth, -deflinear, -defoverlay, or
* -deftransparent is likely to be supported, in which case
* the full spelling of -dev would be needed anyway.
* * No command line option is likely to be given a "-dev"
* argument.
*/
int
const int argc, /* Program argument count */
char * const argv[], /* Program argument vector */
const char **device_arg) /* Returned effective arg to -dev */
{
/*
* Find the (first, if any) -dev option and return its argument
*
* The last argv[] string is ignored. The -dev option
* requires an argument, so "-dev" can't legitimately be the
* last argv[] string. The fbc_getargs() function should
* handle the "Option requires a value" error.
*/
*device_arg = NULL;
break;
}
}
return (FBC_SUCCESS);
} /* fbc_get_device_arg() */
/*
* fbc_resolve_device_links()
*
*
* The device_path_buf buffer is assumed to be unused.
*/
static
int
const char *default_path, /* Default device symlink path */
char *device_path_buf, /* Ptr to device path buffer */
{
int i; /* Symlink loop counter */
/*
* Resolve the symlink to a "/devices/...:<devname>" pathname
*
* A resolved symlink string could resemble one of these (or
* some else unhelpful):
* Examples like the first one are only acceptable as
* intermediate resolutions. Examples like the second are
* what we want ultimately, but might not encounter.
* Examples like the third should be the resolution of the
* final symlink (e.g. second exmple).
*/
if (len >= sizeof (symlink_buf)) {
return (FBC_ERR_READLINK);
}
for (i = 16; ; i -= 1) {
if (i <= 0) {
return (FBC_ERR_READLINK); /* ELOOP */
}
/*
* Resolve this symbolic link (if that's what it is)
*/
if (len < 0) {
break; /* Not a symbolic link */
}
fbc_errormsg("%s, %s\n",
return (FBC_ERR_READLINK);
}
/*
* Make sure the end result is a full pathname
*/
if (respath_buf[0] != '/') {
ptr = &symlink_buf[0];
} else {
ptr += 1;
}
}
return (FBC_ERR_READLINK);
}
}
/*
* Convert "/devices/...:<devname>" to <devname>
*
* Merely assume that the final resolution pathname specifies
* the correct "/devices/..." directory, realizing that it
* actually might look something like this:
*
* The simple filename component must match "*:<devname>".
*/
return (FBC_ERR_READLINK);
}
ptr += 1;
/*
* Construct the device pathname and point to the simple filename
*/
return (FBC_ERR_READLINK);
}
return (FBC_SUCCESS);
} /* fbc_resolve_device_links() */
/*
* fbc_parse_device_filename()
*
* Decompose the device simple filename into:
* * Device "unit" number, if specified, else -1 (arbitrary)
* Return a non-zero error code, FBC_ERR_NAME_LEN, if the
* caller's buffer isn't long enough.
*/
static
int
char *device_type_buf, /* Ptr to device type buffer */
{
/*
* Parse the video stream suffix, if any
*
* If present, the video stream suffix is generally a lower
* case letter, 'a' or 'b', following the unit number, as the
* last character of the simple device name (e.g. 'a' in
* "efb0a"). No video stream suffix will be found if the
* unit number is not present. If no video stream suffix is
* found then store a Nul.
*
* The set of valid video stream suffix characters is
* contained in the FBC_STREAM_SUFFIX_CHARS string. If the
* device name has a video stream suffix that isn't
* appropriate for the device (e.g. 'b' in "kfb0b"), the
* subsequent fbc_open_device() call can be expected to fail.
*
* The actual device->max_streams value should be provided
* later via fbc_get_properties(). We'll use a "safe" value
* until fbc_get_properties() and fbc_revise_device_info()
* can be called.
*/
len -= 1;
}
}
/*
* Parse the frame buffer "unit" number, if any
*/
break;
}
}
if (*cp != '\0') {
}
/*
*/
if (len >= device_type_buflen) {
return (FBC_ERR_NAME_LEN); /* Device type name is too long */
}
/*
*/
return (FBC_SUCCESS);
} /* fbc_parse_device_filename() */
typedef struct {
};
/*
* fbc_get_default_device()
*
* Determine the most likely default frame buffer device (e.g.
* * Simple device filename (e.g. "efb0a")
* * Device "unit" number, if specified, else -1 (arbitrary)
*/
int
char *device_path_buf, /* Ptr to device path buffer */
char *device_type_buf, /* Ptr to device type buffer */
{
/*
* See whether any default device will open and identify itself
*/
return (FBC_ERR_OPEN); /* No default device found */
}
break;
}
}
/*
* Resolve symbolic links and construct the device file pathname
*/
device);
if (error_code != FBC_SUCCESS) {
return (error_code);
}
/*
* Decompose the simple filename of the frame buffer device
*/
return (fbc_parse_device_filename(
} /* fbc_get_default_device() */
/*
* fbc_get_device_name()
*
* Given a -dev argument string, a device pathname buffer, and a
* * Simple device filename (e.g. "efb0a")
* * Device "unit" number, if specified, else -1 (arbitrary)
*
* A caller-supplied buffer might be needed in order to construct the
* full pathname string. Return NULL if the caller's buffer is
* needed but isn't long enough.
*
* The device name string will be extracted into a second, caller-
* supplied buffer. Return an error code if the caller's buffer
* isn't long enough.
*/
int
const char *device_arg, /* Device argument (-dev opt) */
char *device_path_buf, /* Ptr to device path buffer */
char *device_type_buf, /* Ptr to device type buffer */
{
/*
* Assume it's the fully qualified path of a real device
*/
/*
* Resolve any default device name
*/
for (default_dev = &fbc_default_device[0];
default_dev += 1) {
device);
if (error_code != FBC_SUCCESS) {
return (error_code);
}
break;
}
}
/*
*/
/*
* Decompose the simple device name, yeilding its type, etc.
*/
device);
/*
* Determine the device directory path for this device type
*
* should have been done in fbc_get_device_arg().
*/
}
/*
* Construct a full pathname (iff it fits in the buffer)
*/
>= device_path_buflen) {
return (FBC_ERR_PATH_LEN); /* Path is too long */
}
} else {
/*
* Point to the simple device name within the device pathname
*/
/*
* Decompose the frame buffer's simple device name
*/
device);
}
/*
* Return successfully or with a buffer overflow error
*/
return (error_code);
} /* fbc_get_device_name() */
/*
* fbc_revise_device_info()
*
* Finish the video streams initialization that
* fbc_parse_device_filename() didn't have enough information to do.
*
* Before this function can be called, the fbc_get_properties() must
* be called in order to fill in the device->max_streams value.
*/
void
{
/*
* An absent video stream suffix character signifies all streams
*
* A video stream suffix character that is out of range (e.g.
* 'b' in "kfb0b") can be logically ignored here, since the
* subsequent fbc_open_device() call ought to fail.
*/
}
} /* fbc_revise_device_info() */
/* End of fbc_dev.c */