Webcam Library Reference Documentation  Logitech logo
dynctrl.c File Reference

Dynamic control support for the Linux UVC driver. More...

#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <limits.h>
#include <ctype.h>
#include <unistd.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <iconv.h>
#include "webcam.h"
#include "libwebcam.h"
#include "compat.h"
#include <libxml/parser.h>
#include <libxml/tree.h>

Data Structures

struct  _Constant
 Constant read from the XML configuration file. More...
 
struct  _UVCXUControl
 UVC extension unit control for use with UVCIOC_CTRL_ADD. More...
 
struct  _ParseContext
 Helper structure that contains handles and information useful during the XML parsing process. More...
 

Macros

#define _GNU_SOURCE
 
#define HEX_DECODE_CHAR(c)   ((c) >= '0' && (c) <= '9' ? (c) - '0' : (tolower(c)) - 'a' + 0xA)
 Convert a single hex character into its numeric value.
 
#define HEX_DECODE_BYTE(cc)   ((HEX_DECODE_CHAR((cc)[0]) << 4) + HEX_DECODE_CHAR((cc)[1]))
 Convert two hex characters into their byte value.
 
#define UNICODE_TO_ASCII(s)   (unicode_to_ascii(s, ctx))
 Helper macro to convert the UTF-8 strings used by libxml2 into ASCII.
 
#define UNICODE_TO_NORM_ASCII(s)   (unicode_to_normalized_ascii(s, ctx))
 Helper macro to convert the UTF-8 strings used by libxml2 into whitespace normalized ASCII.
 

Typedefs

typedef enum _ConstantType ConstantType
 Type of constants that are allowed in the XML configuration file.
 
typedef struct _Constant Constant
 Constant read from the XML configuration file.
 
typedef struct _UVCXUControl UVCXUControl
 UVC extension unit control for use with UVCIOC_CTRL_ADD.
 
typedef struct _ParseContext ParseContext
 Helper structure that contains handles and information useful during the XML parsing process.
 

Enumerations

enum  _ConstantType { CT_INVALID = 0, CT_INTEGER, CT_GUID }
 Type of constants that are allowed in the XML configuration file. More...
 

Functions

static void guid_to_byte_array (const char *guid, __u8 *array)
 Converts a GUID string into a GUID byte array. More...
 
static int is_valid_integer_string (const char *string, int *value)
 Checks whether a given string contains a valid integer value. More...
 
static int is_valid_size (int value, int max)
 Checks whether a given value represents a valid size. More...
 
static int is_valid_size_string (const char *string, int *value, int max)
 Checks whether a given string represents a valid size. More...
 
static int is_valid_guid (const char *string)
 Checks whether a given string represents a valid GUID.
 
static int string_to_version (const char *string, unsigned int *major, unsigned int *minor)
 Converts a string to a version consisting of major and minor version. More...
 
static __u32 get_uvc_request_by_name (const xmlChar *name)
 Converts the name of a UVC request into its corresponding constant. More...
 
static enum uvc_control_data_type get_uvc_ctrl_type_by_name (const xmlChar *name)
 Converts the name of a UVC data type constant into its corresponding numerical value. More...
 
static enum v4l2_ctrl_type get_v4l2_ctrl_type_by_name (const xmlChar *name)
 Converts the name of a V4L2 data type constant into its corresponding numerical value. More...
 
static char * normalize_string (const char *input)
 Normalizes a string in terms of whitespace. More...
 
static char * unicode_to_ascii (const xmlChar *unicode, ParseContext *ctx)
 Converts a UTF-8 string to ASCII. More...
 
static char * unicode_to_normalized_ascii (const xmlChar *unicode, ParseContext *ctx)
 Converts a UTF-8 string to ASCII and then normalizes the string's whitespace. More...
 
static const xmlChar * xml_get_node_text (const xmlNode *node)
 Returns the text content of the given node. More...
 
static xmlNode * xml_get_first_child_by_name (const xmlNode *node, const char *name)
 Returns the first child node with a given name. More...
 
static xmlNode * xml_get_next_sibling_by_name (const xmlNode *node, const char *name)
 Returns the next sibling node with a given name. More...
 
static Constantlookup_constant (const char *find_name, ConstantType find_type, ParseContext *ctx)
 Look up a constant by its name. More...
 
static CResult lookup_or_convert_to_integer (const xmlChar *text, int *value, ParseContext *ctx)
 Convert the given string to an integer or look up a constant with the given name. More...
 
static CResult lookup_or_convert_to_guid (const xmlChar *text, __u8 *guid, ParseContext *ctx)
 Convert the given string to a GUID or look up a constant with the given name. More...
 
static UVCXUControllookup_control (const xmlChar *name, ParseContext *ctx)
 Lookup a UVC extension unit control with the given name.
 
static CResult resize_message_buffer (ParseContext *ctx, CDynctrlMessage *msg)
 Reorganize the buffer that is used to store the messages that are logged during parsing. More...
 
static CResult add_message_v (ParseContext *ctx, int line, int col, CDynctrlMessageSeverity severity, const char *format, va_list va)
 Adds a new message to the message list. More...
 
static CResult add_message (ParseContext *ctx, int line, int col, CDynctrlMessageSeverity severity, const char *format,...)
 Adds a new message to the message list. More...
 
static CResult add_info (ParseContext *ctx, const char *format,...)
 Adds a new informational message to the message list.
 
static CResult add_error (ParseContext *ctx, const char *format,...)
 Adds a new error message to the message list.
 
static CResult add_error_at_node (ParseContext *ctx, const xmlNode *node, const char *format,...)
 Adds a new error message concerning a given xmlNode to the message list. More...
 
static CResult parse_dynctrl_file (const char *file_name, xmlDoc **xml_doc, ParseContext *ctx)
 Parse a dynamic controls configuration XML file and return an XML document tree. More...
 
static CResult process_mapping (const xmlNode *node_mapping, ParseContext *ctx)
 Process a mapping node and add the contained mapping to the UVC driver.
 
static CResult process_mappings (const xmlNode *node_mappings, ParseContext *ctx)
 Process a mappings node.
 
static CResult process_control (xmlNode *node_control, ParseContext *ctx)
 Process a control node by adding the contained control to the UVC driver.
 
static CResult process_controls (const xmlNode *node_controls, ParseContext *ctx)
 Process a controls node.
 
static CResult process_device (const xmlNode *node_device, ParseContext *ctx)
 Process a device node. More...
 
static CResult process_devices (const xmlNode *node_devices, ParseContext *ctx)
 Process a devices node.
 
static CResult process_constant (xmlNode *node_constant, ParseContext *ctx)
 Process a constant node by adding the contained constant to an internal list.
 
static CResult process_constants (const xmlNode *node_constants, ParseContext *ctx)
 Process a constants node.
 
static CResult process_meta (const xmlNode *node_meta, ParseContext *ctx)
 Process a meta node by filling in the corresponding info structure.
 
static CResult process_dynctrl_doc (xmlDoc *xml_doc, ParseContext *ctx)
 Process an XML document tree representing a dynamic controls configuration file.
 
static CResult device_supports_dynctrl (ParseContext *ctx)
 Checks whether the driver behind the current device supports dynamic controls. More...
 
static CResult add_control_mappings (xmlDoc *xml_doc, ParseContext *ctx)
 Adds controls and control mappings contained in the given XML tree to the UVC driver. More...
 
CResult c_add_control_mappings_from_file (const char *file_name, CDynctrlInfo *info)
 Parses a dynamic controls configuration file and adds the contained controls and control mappings to the UVC driver. More...
 

Detailed Description

Dynamic control support for the Linux UVC driver.

Enumeration Type Documentation

Type of constants that are allowed in the XML configuration file.

Enumerator
CT_INVALID 

Invalid type (used internally)

CT_INTEGER 

Signed integer constant.

CT_GUID 

GUID.

Function Documentation

static CResult add_control_mappings ( xmlDoc *  xml_doc,
ParseContext ctx 
)
static

Adds controls and control mappings contained in the given XML tree to the UVC driver.

Parameters
xml_docXML document tree corresponding to the dynctrl format
ctxcurrent parse context
Returns

References C_INVALID_DEVICE, C_SUCCESS, device_supports_dynctrl(), GET_HANDLE, _ParseContext::handle, HANDLE_OPEN, HANDLE_VALID, open_v4l2_device(), process_dynctrl_doc(), and _ParseContext::v4l2_handle.

Referenced by c_add_control_mappings_from_file().

static CResult add_error_at_node ( ParseContext ctx,
const xmlNode *  node,
const char *  format,
  ... 
)
static

Adds a new error message concerning a given xmlNode to the message list.

The node is used to extract the line number.

References add_message_v(), and CD_SEVERITY_ERROR.

Referenced by process_constant(), process_control(), and process_mapping().

static CResult add_message ( ParseContext ctx,
int  line,
int  col,
CDynctrlMessageSeverity  severity,
const char *  format,
  ... 
)
static

Adds a new message to the message list.

Parameters
ctxcurrent parse context
lineline number that the message concerns (e.g. line of the syntax error)
colcolumn number that the message concerns
severityseverity level of the message (warning, error, etc.)
formata printf compatible format to print the variable parameter list

References add_message_v().

Referenced by parse_dynctrl_file().

static CResult add_message_v ( ParseContext ctx,
int  line,
int  col,
CDynctrlMessageSeverity  severity,
const char *  format,
va_list  va 
)
static

Adds a new message to the message list.

This function works like add_message() but takes a va_list argument instead of a parameter list.

References C_INVALID_ARG, C_NO_MEMORY, C_SUCCESS, CD_REPORT_ERRORS, _CDynctrlMessage::col, _CDynctrlInfo::flags, _ParseContext::info, _CDynctrlMessage::line, resize_message_buffer(), _CDynctrlMessage::severity, and _CDynctrlMessage::text.

Referenced by add_error(), add_error_at_node(), add_info(), and add_message().

CResult c_add_control_mappings_from_file ( const char *  file_name,
CDynctrlInfo info 
)

Parses a dynamic controls configuration file and adds the contained controls and control mappings to the UVC driver.

Notes:

  • Just because the function returns C_SUCCESS doesn't mean there were no errors. The dynamic controls parsing process tries to be very forgiving on syntax errors or if processing of a single control/mapping fails. Check the info->messages list for details after processing is done.
  • If the info parameter is not NULL the caller must free the info->messages field if it is not NULL.
  • Note that this function is not thread-safe.
Parameters
file_namename of the device to open.
infostructure to pass operation flags and retrieve status information. Can be NULL.
Returns

References add_control_mappings(), add_error(), add_info(), C_BUFFER_TOO_SMALL, C_CANNOT_WRITE, c_close_device(), c_enum_devices(), c_get_handle_error_text(), C_INIT_ERROR, C_INVALID_ARG, C_INVALID_DEVICE, C_NO_MEMORY, C_NOT_IMPLEMENTED, c_open_device(), C_SUCCESS, _ParseContext::cd, _ParseContext::constants, _ParseContext::controls, _CDevice::driver, _ParseContext::handle, _UVCXUControl::id, _ParseContext::info, initialized, _Constant::name, _Constant::next, _UVCXUControl::next, parse_dynctrl_file(), and _CDevice::shortName.

static CResult device_supports_dynctrl ( ParseContext ctx)
static

Checks whether the driver behind the current device supports dynamic controls.

The check is done by redefining the brightness control which is hardcoded in the UVC driver. If the driver supports dynamic controls, it will return EEXIST. If the driver does not support dynamic controls, the ioctl will fail with EINVAL.

Parameters
ctxcurrent parse context
Returns

References C_CANNOT_WRITE, C_NOT_IMPLEMENTED, C_SUCCESS, and _ParseContext::v4l2_handle.

Referenced by add_control_mappings().

static enum uvc_control_data_type get_uvc_ctrl_type_by_name ( const xmlChar *  name)
static

Converts the name of a UVC data type constant into its corresponding numerical value.

Parameters
namedata type string to be converted. Can be NULL.
Returns
  • -1 if the conversion failed, i.e. the data type name was not recognized
  • a UVC_CTRL_DATA_TYPE_* constant if the conversion was successful

Referenced by process_mapping().

static __u32 get_uvc_request_by_name ( const xmlChar *  name)
static

Converts the name of a UVC request into its corresponding constant.

Parameters
namerequest string to be converted. Can be NULL.
Returns
  • 0 if the conversion failed, i.e. the request name was not recognized
  • a UVC_CONTROL_* constant if the conversion was successful

Referenced by process_control().

static enum v4l2_ctrl_type get_v4l2_ctrl_type_by_name ( const xmlChar *  name)
static

Converts the name of a V4L2 data type constant into its corresponding numerical value.

Note that not all V4L2 data types are recognized. Only the ones relevant for libwebcam and allowed by the schema are considered valid.

Parameters
namedata type string to be converted. Can be NULL.
Returns
  • 0 if the conversion failed, i.e. the data type name was not recognized
  • a V4L2_CTRL_TYPE_* constant if the conversion was successful

Referenced by process_mapping().

static void guid_to_byte_array ( const char *  guid,
__u8 *  array 
)
static

Converts a GUID string into a GUID byte array.

This function assumes that guid is a valid GUID string. No validation is performed.

References HEX_DECODE_BYTE.

Referenced by lookup_or_convert_to_guid(), and process_constant().

static int is_valid_integer_string ( const char *  string,
int *  value 
)
static

Checks whether a given string contains a valid integer value.

This function considers all integers recognized by strtol() as valid. This includes hexadecimal numbers with a '0x' prefix and octal numbers with a leading zero.

Parameters
stringString containing an integer. Can be NULL.
valueA pointer in which the converted value will be stored. Can be NULL if conversion is not required.
Returns
boolean indicating whether the string represents a valid integer

Referenced by is_valid_size_string(), lookup_or_convert_to_integer(), and process_constant().

static int is_valid_size ( int  value,
int  max 
)
inlinestatic

Checks whether a given value represents a valid size.

Only positive numbers are considered valid size values. In addition, an upper threshold can be specified, above which values will be considered invalid.

Parameters
valuevalue to be checked
maxupper threshold for the validity of value. If the threshold is negative, no threshold check is performed, i.e. max == INT_MAX is assumed.
Returns
boolean indicating whether the value is a valid size

Referenced by is_valid_size_string(), and process_control().

static int is_valid_size_string ( const char *  string,
int *  value,
int  max 
)
static

Checks whether a given string represents a valid size.

This function works just like is_valid_size() but accepts an input string and a buffer to store the converted value.

References is_valid_integer_string(), and is_valid_size().

Referenced by process_mapping().

static Constant* lookup_constant ( const char *  find_name,
ConstantType  find_type,
ParseContext ctx 
)
static

Look up a constant by its name.

Parameters
ctxcurrent parse context
find_namename of the constant to look up
find_typeonly search for constants with this type. Specify CT_INVALID to disable the type filter.
Returns
  • NULL if no constant with the given name (and given type) could be found
  • a pointer to the constant if the search was successful

References _ParseContext::constants, CT_INVALID, _Constant::name, _Constant::next, and _Constant::type.

Referenced by lookup_or_convert_to_guid(), lookup_or_convert_to_integer(), and process_constant().

static CResult lookup_or_convert_to_guid ( const xmlChar *  text,
__u8 *  guid,
ParseContext ctx 
)
static

Convert the given string to a GUID or look up a constant with the given name.

This function works like lookup_or_convert_to_integer() except that it looks for GUIDs instead of integers.

References C_PARSE_ERROR, C_SUCCESS, CT_GUID, _Constant::guid, GUID_SIZE, guid_to_byte_array(), is_valid_guid(), and lookup_constant().

Referenced by process_control().

static CResult lookup_or_convert_to_integer ( const xmlChar *  text,
int *  value,
ParseContext ctx 
)
static

Convert the given string to an integer or look up a constant with the given name.

The function first tries to convert the given string to an integer. If successful, the converted value is returned. If the conversion fails, the string is interpreted as a name and a constant with that name is looked up. If the lookup is successful, the value of the constant is returned.

Parameters
textpointer to the name or integer value. Can be NULL.
valuepointer to an integer to receive the converted or constant value
ctxcurrent parse context
Returns
  • C_SUCCESS if the string was successfully converted to an integer
  • C_SUCCESS if the string was not converted but a constant was found
  • C_PARSE_ERROR if text is NULL, or if both conversion and lookup fail

References C_PARSE_ERROR, C_SUCCESS, CT_INTEGER, is_valid_integer_string(), lookup_constant(), and _Constant::value.

Referenced by process_control(), and process_mapping().

static char* normalize_string ( const char *  input)
static

Normalizes a string in terms of whitespace.

The function returns a copy of the input string with leading and trailing whitespace removed and all internal whitespace reduced to simple spaces. Examples: " text " => "text" " Multi\nline text" => "Multi line text"

This function allocates a new buffer that needs to be freed by the caller.

Parameters
inputinput string to be normalized. This string is not modified.
Returns
  • NULL if input is NULL or if memory could not be allocated
  • a newly allocated buffer containing the output string

Referenced by unicode_to_normalized_ascii().

static CResult parse_dynctrl_file ( const char *  file_name,
xmlDoc **  xml_doc,
ParseContext ctx 
)
static

Parse a dynamic controls configuration XML file and return an XML document tree.

Note that the pointer stored in *xml_doc must be freed using xmlFreeDoc() if the return value of this functino is C_SUCCESS.

Parameters
file_namename (with an optional path) of the file to be parsed
xml_docaddress of a pointer to store the XML document tree
ctxcurrent parse context
Returns
  • C_NO_MEMORY if a buffer or structure could not be allocated
  • C_PARSE_ERROR if the XML file is malformed
  • C_SUCCESS if parsing was successful

References add_message(), C_NO_MEMORY, C_PARSE_ERROR, C_SUCCESS, CD_DONT_VALIDATE, CD_SEVERITY_ERROR, _CDynctrlInfo::flags, and _ParseContext::info.

Referenced by c_add_control_mappings_from_file().

static CResult process_device ( const xmlNode *  node_device,
ParseContext ctx 
)
static

Process a device node.

Note that the contained match sections are currently ignored.

References C_SUCCESS, process_controls(), and xml_get_first_child_by_name().

Referenced by process_devices().

static CResult resize_message_buffer ( ParseContext ctx,
CDynctrlMessage msg 
)
static

Reorganize the buffer that is used to store the messages that are logged during parsing.

The buffer that is used to store the messages is completely self-contained. It consists of an array of CDynctrlMessage structures and an area for "dynamics" which stores dynamic data like strings. All string pointers in the array point to strings in the dynamics area, so for clean up only a single buffer needs to be freed.

Every time a new array element is added, the buffer has to be enlarged, and a new array element has to be inserted between the current last element and the dynamics area. The dynamics area is moved by sizeof(CDynctrlMessage) bytes and all pointers to it are updated to point to the new direction.

Parameters
ctxcurrent parse context
msgpointer to the new message to be added. Note that this is only a temporary buffer. Its content (including its strings) is copied into the message buffer and the temporary buffer is no longer required after the function returns.
Returns
  • C_NO_MEMORY if the buffer could not be enlarged for lack of memory
  • C_SUCCESS otherwise

References C_NO_MEMORY, C_SUCCESS, _ParseContext::info, _CDynctrlInfo::message_count, _CDynctrlInfo::messages, _ParseContext::messages_size, and _CDynctrlMessage::text.

Referenced by add_message_v().

static int string_to_version ( const char *  string,
unsigned int *  major,
unsigned int *  minor 
)
static

Converts a string to a version consisting of major and minor version.

Accepted formats are "x.y" and "x" where x is the major and y the minor version.

Parameters
stringversion string to be converted
majorpointer to an integer where the major version number should be stored
minorpointer to an integer where the minor version number should be stored
Returns
boolean indicating whether the conversion succeeded or not

Referenced by process_meta().

static char* unicode_to_ascii ( const xmlChar *  unicode,
ParseContext ctx 
)
static

Converts a UTF-8 string to ASCII.

The function may convert some characters in a non-reversible way.

Parameters
unicodeinput string to be converted.
ctxcurrent parse context
Returns
  • NULL if the input buffer is NULL or an error occurs
  • a copy of the input string if there is no iconv conversion descriptor
  • a newly allocated buffer containing only ASCII characters

References _ParseContext::cd.

Referenced by process_meta(), and unicode_to_normalized_ascii().

static char* unicode_to_normalized_ascii ( const xmlChar *  unicode,
ParseContext ctx 
)
static

Converts a UTF-8 string to ASCII and then normalizes the string's whitespace.

This function is effectively a combination of unicode_to_ascii() and normalize_string(). Note that the caller must free the returned string.

References normalize_string(), and unicode_to_ascii().

Referenced by process_meta().

static xmlNode* xml_get_first_child_by_name ( const xmlNode *  node,
const char *  name 
)
static

Returns the first child node with a given name.

Parameters
nodepointer to the parent node whose children are to be searched
namethe name of the child node to be searched for
Returns
  • a pointer to the first child node with the given name
  • NULL if no child node has the given name

Referenced by process_constant(), process_constants(), process_control(), process_controls(), process_device(), process_devices(), process_dynctrl_doc(), process_mapping(), process_mappings(), and process_meta().

static xmlNode* xml_get_next_sibling_by_name ( const xmlNode *  node,
const char *  name 
)
static

Returns the next sibling node with a given name.

Parameters
nodepointer to the node whose siblings are to be searched
namethe name of the sibling node to be searched for
Returns
  • a pointer to the first sibling node with the given name
  • NULL if no sibling node has the given name

Referenced by process_constants(), process_control(), process_controls(), process_devices(), process_dynctrl_doc(), and process_mappings().

static const xmlChar* xml_get_node_text ( const xmlNode *  node)
static

Returns the text content of the given node.

Parameters
nodePointer to a node. May be NULL.
Returns
  • the content of the first text child node if it exists
  • NULL if a node in the path does not exist or does not contain text

Referenced by process_constant(), process_control(), process_mapping(), and process_meta().


Generated on Sun Apr 28 2013 23:41:32 for Webcam Library by Doxygen 1.8.3.1
Copyright © 2006-2008 Logitech.