libwebcam-src-0.2.4/0000755000175000017500000000000012234550326013253 5ustar paulopaulolibwebcam-src-0.2.4/build/0000755000175000017500000000000012234547770014363 5ustar paulopaulolibwebcam-src-0.2.4/CMakeLists.txt0000644000175000017500000000073012234547770016024 0ustar paulopaulo# # GENERAL # # Require CMake 2.6 because of the Debian packaging. cmake_minimum_required (VERSION 2.6) # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) # # SUBDIRECTORIES # add_subdirectory (libwebcam) add_subdirectory (uvcdynctrl) libwebcam-src-0.2.4/.gitignore0000644000175000017500000000075012234547770015256 0ustar paulopaulo# Compiled source # ################### *.com *.class *.dll *.exe *.o *.so # Packages # ############ # it's better to unpack these files and commit the raw source # git has its own built in compression methods *.7z *.dmg *.gz *.iso *.jar *.rar *.tar *.zip # Patches # ########### *.patch # temp files# ############# *~ *.swp *.tmp # Logs and databases # ###################### *.log *.sql *.sqlite # OS generated files # ###################### .DS_Store* ehthumbs.db Icon? Thumbs.db libwebcam-src-0.2.4/cmake_uninstall.cmake.in0000644000175000017500000000210312234547770020040 0ustar paulopauloif (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") if(POLICY CMP0007) cmake_policy(SET CMP0007 NEW) endif(POLICY CMP0007) file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) string(REGEX REPLACE "\n" ";" files "${files}") list(REVERSE files) foreach (file ${files}) message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") if (EXISTS "$ENV{DESTDIR}${file}") execute_process( COMMAND @CMAKE_COMMAND@ -E remove "$ENV{DESTDIR}${file}" OUTPUT_VARIABLE rm_out RESULT_VARIABLE rm_retval ) if(NOT ${rm_retval} EQUAL 0) message(FATAL_ERROR "Problem when uninstalling \"$ENV{DESTDIR}${file}\"") endif (NOT ${rm_retval} EQUAL 0) else (EXISTS "$ENV{DESTDIR}${file}") message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") endif (EXISTS "$ENV{DESTDIR}${file}") endforeach(file) libwebcam-src-0.2.4/uvcdynctrl/0000755000175000017500000000000012234547770015461 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/cmdline.c0000644000175000017500000005517412234547770017254 0ustar paulopaulo/* File autogenerated by gengetopt version 2.22 generated with the following command: gengetopt -i uvcdynctrl.ggo --output-dir uvcdynctrl --unamed-opts=VALUES The developers of gengetopt consider the fixed text that goes in all gengetopt output files to be in the public domain: we make no copyright claims on it. */ /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include "getopt.h" #include "cmdline.h" const char *gengetopt_args_info_purpose = "Manage dynamic controls in uvcvideo"; const char *gengetopt_args_info_usage = "Usage: uvcdynctrl [OPTIONS]... [VALUES]..."; const char *gengetopt_args_info_description = ""; const char *gengetopt_args_info_help[] = { " -h, --help Print help and exit", " -V, --version Print version and exit", " -l, --list List available cameras", " -i, --import=filename Import dynamic controls from an XML file", " -a, --addctrl=vid Import dynamic controls for vid from default location", " -v, --verbose Enable verbose output (default=off)", " -d, --device=devicename Specify the device to use (default=`video0')", " -c, --clist List available controls", " -g, --get=control Retrieve the current control value", " -G, --get_raw=unit_id:selector Retrieve the current raw control value", " -s, --set=control Set a new control value\n" " (For negative values: -s 'My Control' -- -42)", " -S, --set_raw=unit_id:selector Set the current raw control value\n" " (value is a hex string of control size,\n" " default is little endian- '(BE)' prefix to change:\n" " -S 13:1 0x01100c or -S 13:1 '(BE)0x0c1001' )\n", " -f, --formats List available frame formats", " -W, --save=filename Save device controls state to a file", " -L, --load=filename Load device controls state from a file", 0 }; typedef enum {ARG_NO , ARG_FLAG , ARG_STRING } cmdline_parser_arg_type; static void clear_given (struct gengetopt_args_info *args_info); static void clear_args (struct gengetopt_args_info *args_info); static int cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error); static char * gengetopt_strdup (const char *s); static void clear_given (struct gengetopt_args_info *args_info) { args_info->help_given = 0 ; args_info->version_given = 0 ; args_info->list_given = 0 ; args_info->import_given = 0 ; args_info->addctrl_given = 0 ; args_info->verbose_given = 0 ; args_info->device_given = 0 ; args_info->clist_given = 0 ; args_info->get_given = 0 ; args_info->get_raw_given = 0 ; args_info->set_given = 0 ; args_info->set_raw_given = 0 ; args_info->formats_given = 0 ; args_info->save_ctrl_given = 0 ; args_info->load_ctrl_given = 0 ; } static void clear_args (struct gengetopt_args_info *args_info) { args_info->import_arg = NULL; args_info->import_orig = NULL; args_info->addctrl_arg = NULL; args_info->addctrl_orig = NULL; args_info->verbose_flag = 0; args_info->device_arg = gengetopt_strdup ("video0"); args_info->device_orig = NULL; args_info->get_arg = NULL; args_info->get_orig = NULL; args_info->get_raw_arg = NULL ; args_info->get_raw_orig = NULL ; args_info->set_arg = NULL; args_info->set_orig = NULL; args_info->set_raw_arg = NULL ; args_info->set_raw_orig = NULL ; args_info->save_ctrl_arg = NULL; args_info->save_ctrl_orig = NULL; args_info->load_ctrl_arg = NULL; args_info->load_ctrl_orig = NULL; } static void init_args_info(struct gengetopt_args_info *args_info) { args_info->help_help = gengetopt_args_info_help[0] ; args_info->version_help = gengetopt_args_info_help[1] ; args_info->list_help = gengetopt_args_info_help[2] ; args_info->import_help = gengetopt_args_info_help[3] ; args_info->addctrl_help = gengetopt_args_info_help[4] ; args_info->verbose_help = gengetopt_args_info_help[5] ; args_info->device_help = gengetopt_args_info_help[6] ; args_info->clist_help = gengetopt_args_info_help[7] ; args_info->get_help = gengetopt_args_info_help[8] ; args_info->get_raw_help = gengetopt_args_info_help[9] ; args_info->set_help = gengetopt_args_info_help[10] ; args_info->set_raw_help = gengetopt_args_info_help[11] ; args_info->formats_help = gengetopt_args_info_help[12] ; args_info->save_ctrl_help = gengetopt_args_info_help[13] ; args_info->load_ctrl_help = gengetopt_args_info_help[14] ; } void cmdline_parser_print_version (void) { printf ("%s %s\n", CMDLINE_PARSER_PACKAGE, CMDLINE_PARSER_VERSION); } static void print_help_common(void) { cmdline_parser_print_version (); if (strlen(gengetopt_args_info_purpose) > 0) printf("\n%s\n", gengetopt_args_info_purpose); if (strlen(gengetopt_args_info_usage) > 0) printf("\n%s\n", gengetopt_args_info_usage); printf("\n"); if (strlen(gengetopt_args_info_description) > 0) printf("%s\n", gengetopt_args_info_description); } void cmdline_parser_print_help (void) { int i = 0; print_help_common(); while (gengetopt_args_info_help[i]) printf("%s\n", gengetopt_args_info_help[i++]); } void cmdline_parser_init (struct gengetopt_args_info *args_info) { clear_given (args_info); clear_args (args_info); init_args_info (args_info); args_info->inputs = NULL; args_info->inputs_num = 0; } void cmdline_parser_params_init(struct cmdline_parser_params *params) { if (params) { params->override = 0; params->initialize = 1; params->check_required = 1; params->check_ambiguity = 0; params->print_errors = 1; } } struct cmdline_parser_params * cmdline_parser_params_create(void) { struct cmdline_parser_params *params = (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params)); cmdline_parser_params_init(params); return params; } static void free_string_field (char **s) { if (*s) { free (*s); *s = 0; } } static void cmdline_parser_release (struct gengetopt_args_info *args_info) { unsigned int i; free_string_field (&(args_info->import_arg)); free_string_field (&(args_info->import_orig)); free_string_field (&(args_info->addctrl_arg)); free_string_field (&(args_info->addctrl_orig)); free_string_field (&(args_info->device_arg)); free_string_field (&(args_info->device_orig)); free_string_field (&(args_info->get_arg)); free_string_field (&(args_info->get_orig)); free_string_field (&(args_info->get_raw_arg)); free_string_field (&(args_info->get_raw_orig)); free_string_field (&(args_info->set_arg)); free_string_field (&(args_info->set_orig)); free_string_field (&(args_info->set_raw_arg)); free_string_field (&(args_info->set_raw_orig)); free_string_field (&(args_info->save_ctrl_arg)); free_string_field (&(args_info->save_ctrl_orig)); free_string_field (&(args_info->load_ctrl_arg)); free_string_field (&(args_info->load_ctrl_orig)); for (i = 0; i < args_info->inputs_num; ++i) free (args_info->inputs [i]); if (args_info->inputs_num) free (args_info->inputs); clear_given (args_info); } static void write_into_file(FILE *outfile, const char *opt, const char *arg, char *values[]) { if (arg) { fprintf(outfile, "%s=\"%s\"\n", opt, arg); } else { fprintf(outfile, "%s\n", opt); } } int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info) { int i = 0; if (!outfile) { fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE); return EXIT_FAILURE; } if (args_info->help_given) write_into_file(outfile, "help", 0, 0 ); if (args_info->version_given) write_into_file(outfile, "version", 0, 0 ); if (args_info->list_given) write_into_file(outfile, "list", 0, 0 ); if (args_info->import_given) write_into_file(outfile, "import", args_info->import_orig, 0); if (args_info->addctrl_given) write_into_file(outfile, "addctrl", args_info->addctrl_orig, 0); if (args_info->verbose_given) write_into_file(outfile, "verbose", 0, 0 ); if (args_info->device_given) write_into_file(outfile, "device", args_info->device_orig, 0); if (args_info->clist_given) write_into_file(outfile, "clist", 0, 0 ); if (args_info->get_given) write_into_file(outfile, "get", args_info->get_orig, 0); if (args_info->get_raw_given) write_into_file(outfile, "get_raw", args_info->get_raw_orig, 0); if (args_info->set_given) write_into_file(outfile, "set", args_info->set_orig, 0); if (args_info->set_raw_given) write_into_file(outfile, "set_raw", args_info->set_raw_orig, 0); if (args_info->formats_given) write_into_file(outfile, "formats", 0, 0 ); if (args_info->save_ctrl_given) write_into_file(outfile, "save", args_info->save_ctrl_orig, 0 ); if (args_info->load_ctrl_given) write_into_file(outfile, "save", args_info->load_ctrl_orig, 0 ); i = EXIT_SUCCESS; return i; } int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info) { FILE *outfile; int i = 0; outfile = fopen(filename, "w"); if (!outfile) { fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename); return EXIT_FAILURE; } i = cmdline_parser_dump(outfile, args_info); fclose (outfile); return i; } void cmdline_parser_free (struct gengetopt_args_info *args_info) { cmdline_parser_release (args_info); } /** @brief replacement of strdup, which is not standard */ char * gengetopt_strdup (const char *s) { char *result = NULL; if (!s) return result; result = (char*)malloc(strlen(s) + 1); if (result == (char*)0) return (char*)0; strcpy(result, s); return result; } int cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info) { return cmdline_parser2 (argc, argv, args_info, 0, 1, 1); } int cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params) { int result; result = cmdline_parser_internal (argc, argv, args_info, params, NULL); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required) { int result; struct cmdline_parser_params params; params.override = override; params.initialize = initialize; params.check_required = check_required; params.check_ambiguity = 0; params.print_errors = 1; result = cmdline_parser_internal (argc, argv, args_info, ¶ms, NULL); if (result == EXIT_FAILURE) { cmdline_parser_free (args_info); exit (EXIT_FAILURE); } return result; } int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name) { return EXIT_SUCCESS; } static char *package_name = 0; /** * @brief updates an option * @param field the generic pointer to the field to update * @param orig_field the pointer to the orig field * @param field_given the pointer to the number of occurrence of this option * @param prev_given the pointer to the number of occurrence already seen * @param value the argument for this option (if null no arg was specified) * @param possible_values the possible values for this option (if specified) * @param default_value the default value (in case the option only accepts fixed values) * @param arg_type the type of this option * @param check_ambiguity @see cmdline_parser_params.check_ambiguity * @param override @see cmdline_parser_params.override * @param no_free whether to free a possible previous value * @param multiple_option whether this is a multiple option * @param long_opt the corresponding long option * @param short_opt the corresponding short option (or '-' if none) * @param additional_error possible further error specification */ static int update_arg(void *field, char **orig_field, unsigned int *field_given, unsigned int *prev_given, char *value, char *possible_values[], const char *default_value, cmdline_parser_arg_type arg_type, int check_ambiguity, int override, int no_free, int multiple_option, const char *long_opt, char short_opt, const char *additional_error) { //char *stop_char = 0; const char *val = value; int found; char **string_field; //stop_char = 0; found = 0; if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given))) { if (short_opt != '-') fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", package_name, long_opt, short_opt, (additional_error ? additional_error : "")); else fprintf (stderr, "%s: `--%s' option given more than once%s\n", package_name, long_opt, (additional_error ? additional_error : "")); return 1; /* failure */ } if (field_given && *field_given && ! override) return 0; if (prev_given) (*prev_given)++; if (field_given) (*field_given)++; if (possible_values) val = possible_values[found]; switch(arg_type) { case ARG_FLAG: *((int *)field) = !*((int *)field); break; case ARG_STRING: if (val) { string_field = (char **)field; if (!no_free && *string_field) free (*string_field); /* free previous string */ *string_field = gengetopt_strdup (val); } break; default: break; }; /* store the original value */ switch(arg_type) { case ARG_NO: case ARG_FLAG: break; default: if (value && orig_field) { if (no_free) { *orig_field = value; } else { if (*orig_field) free (*orig_field); /* free previous string */ *orig_field = gengetopt_strdup (value); } } }; return 0; /* OK */ } int cmdline_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params, const char *additional_error) { int c; /* Character of the parsed option. */ int error = 0; struct gengetopt_args_info local_args_info; int override; int initialize; //int check_required; int check_ambiguity; package_name = argv[0]; override = params->override; initialize = params->initialize; //check_required = params->check_required; check_ambiguity = params->check_ambiguity; if (initialize) cmdline_parser_init (args_info); cmdline_parser_init (&local_args_info); optarg = 0; optind = 0; opterr = params->print_errors; optopt = '?'; while (1) { int option_index = 0; static struct option long_options[] = { { "help", 0, NULL, 'h' }, { "version",0, NULL, 'V' }, { "list", 0, NULL, 'l' }, { "import", 1, NULL, 'i' }, { "addctrl",1, NULL, 'a' }, { "verbose",0, NULL, 'v' }, { "device", 1, NULL, 'd' }, { "clist", 0, NULL, 'c' }, { "get", 1, NULL, 'g' }, { "get_raw",1, NULL, 'G' }, { "set", 1, NULL, 's' }, { "set_raw",1, NULL, 'S' }, { "formats",0, NULL, 'f' }, { "save", 1, NULL, 'W' }, { "load", 1, NULL, 'L' }, { NULL, 0, NULL, 0 } }; c = getopt_long (argc, argv, "hVli:a:vd:cg:G:s:S:fW:L:", long_options, &option_index); if (c == -1) break; /* Exit from `while (1)' loop. */ switch (c) { case 'h': /* Print help and exit. */ cmdline_parser_print_help (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'V': /* Print version and exit. */ cmdline_parser_print_version (); cmdline_parser_free (&local_args_info); exit (EXIT_SUCCESS); case 'l': /* List available cameras. */ if (update_arg( 0 , 0 , &(args_info->list_given), &(local_args_info.list_given), optarg, 0, 0, ARG_NO, check_ambiguity, override, 0, 0, "list", 'l', additional_error)) goto failure; break; case 'i': /* Import dynamic controls from an XML file. */ if (update_arg( (void *)&(args_info->import_arg), &(args_info->import_orig), &(args_info->import_given), &(local_args_info.import_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "import", 'i', additional_error)) goto failure; break; case 'a': /* Add dynamic controls from XML files at default location */ if (update_arg( (void *)&(args_info->addctrl_arg), &(args_info->addctrl_orig), &(args_info->addctrl_given), &(local_args_info.addctrl_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "addctrl", 'a', additional_error)) goto failure; break; case 'v': /* Enable verbose output. */ if (update_arg((void *)&(args_info->verbose_flag), 0, &(args_info->verbose_given), &(local_args_info.verbose_given), optarg, 0, 0, ARG_FLAG, check_ambiguity, override, 1, 0, "verbose", 'v', additional_error)) goto failure; break; case 'd': /* Specify the device to use. */ if (update_arg( (void *)&(args_info->device_arg), &(args_info->device_orig), &(args_info->device_given), &(local_args_info.device_given), optarg, 0, "video0", ARG_STRING, check_ambiguity, override, 0, 0, "device", 'd', additional_error)) goto failure; break; case 'c': /* List available controls. */ if (update_arg( 0 , 0 , &(args_info->clist_given), &(local_args_info.clist_given), optarg, 0, 0, ARG_NO, check_ambiguity, override, 0, 0, "clist", 'c', additional_error)) goto failure; break; case 'g': /* Retrieve the current control value. */ if (update_arg( (void *)&(args_info->get_arg), &(args_info->get_orig), &(args_info->get_given), &(local_args_info.get_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "get", 'g', additional_error)) goto failure; break; case 'G': /* Retrieve the current raw control value. */ if (update_arg( (void *)&(args_info->get_raw_arg), &(args_info->get_raw_orig), &(args_info->get_raw_given), &(local_args_info.get_raw_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "get_raw", 'G', additional_error)) goto failure; break; case 's': /* Set a new control value\n(For negative values: -s 'My Control' -- -42). */ if (update_arg( (void *)&(args_info->set_arg), &(args_info->set_orig), &(args_info->set_given), &(local_args_info.set_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "set", 's', additional_error)) goto failure; break; case 'S': /* Save the current raw control value. */ if (update_arg( (void *)&(args_info->set_raw_arg), &(args_info->set_raw_orig), &(args_info->set_raw_given), &(local_args_info.set_raw_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "set_raw", 'S', additional_error)) goto failure; break; case 'f': /* List available frame formats. */ if (update_arg( 0 , 0 , &(args_info->formats_given), &(local_args_info.formats_given), optarg, 0, 0, ARG_NO, check_ambiguity, override, 0, 0, "formats", 'f', additional_error)) goto failure; break; case 'W': /* save controls to a file. */ if (update_arg( (void *)&(args_info->save_ctrl_arg), &(args_info->save_ctrl_orig), &(args_info->save_ctrl_given), &(local_args_info.save_ctrl_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "save", 'W', additional_error)) goto failure; break; case 'L': /* load controls from a file. */ if (update_arg( (void *)&(args_info->load_ctrl_arg), &(args_info->load_ctrl_orig), &(args_info->load_ctrl_given), &(local_args_info.load_ctrl_given), optarg, 0, 0, ARG_STRING, check_ambiguity, override, 0, 0, "load", 'L', additional_error)) goto failure; break; case 0: /* Long option with no short option */ case '?': /* Invalid option. */ /* `getopt_long' already printed an error message. */ goto failure; default: /* bug: option not considered. */ fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : "")); abort (); } /* switch */ } /* while */ cmdline_parser_release (&local_args_info); if ( error ) return (EXIT_FAILURE); if (optind < argc) { int i = 0 ; int found_prog_name = 0; /* whether program name, i.e., argv[0], is in the remaining args (this may happen with some implementations of getopt, but surely not with the one included by gengetopt) */ i = optind; while (i < argc) if (argv[i++] == argv[0]) { found_prog_name = 1; break; } i = 0; args_info->inputs_num = argc - optind - found_prog_name; args_info->inputs = (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ; while (optind < argc) if (argv[optind++] != argv[0]) args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind-1]) ; } return 0; failure: cmdline_parser_release (&local_args_info); return (EXIT_FAILURE); } libwebcam-src-0.2.4/uvcdynctrl/COPYING0000644000175000017500000010451312234547770016520 0ustar paulopaulo GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . libwebcam-src-0.2.4/uvcdynctrl/config.h.cmake0000644000175000017500000000064212234547770020160 0ustar paulopaulo#define STRINGIFY_(s) #s #define STRINGIFY(s) STRINGIFY_(s) #define UVCDYNCTRL_VERSION ${UVCDYNCTRL_VERSION} #ifndef UVCDYNCTRL_VERSION #define UVCDYNCTRL_VERSION 0.0 #endif #define VERSION STRINGIFY(UVCDYNCTRL_VERSION) #define UVCDYNCTRL_DATA_DIR ${UVCDYNCTRL_DATA_DIR}/data #ifndef UVCDYNCTRL_DATA_DIR #define UVCDYNCTRL_DATA_DIR /usr/share/uvcdynctrl/data #endif #define DATA_DIR STRINGIFY(UVCDYNCTRL_DATA_DIR) libwebcam-src-0.2.4/uvcdynctrl/controls.c0000644000175000017500000001260112234547770017470 0ustar paulopaulo/* * uvcdynctrl - Manage dynamic controls in uvcvideo * * * Copyright (c) 2006-2007 Logitech. * * This file is part of uvcdynctrl. * * uvcdynctrl is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * uvcdynctrl 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 uvcdynctrl. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "controls.h" /* * Convert a array of bytes from big endian to little endian and vice versa by inverting it */ static uint8_t *raw_inv(uint8_t *data, int size) { int ai = 0; int bi = size - 1; uint8_t a = 0; uint8_t b = 0; while (ai < bi) { a = data[ai]; b = data[bi]; data[ai] = b; data[bi] = a; ai++; bi--; } return data; } /* * Convert char array to 1 byte */ static uint8_t convert_byte(char str[2], int base) { uint8_t val = 0; int i = 0; uint8_t mult[2] = {1, base}; if (base == 16) { for(i=0; i<2; i++) { if (isdigit(str[i])) { val += (str[i] - '0') * mult[i]; } else if (isalpha(str[i]) && (toupper(str[i]) >= 'A') && (toupper(str[i]) <= 'F')) { val += (10 + (toupper(str[i]) - 'A')) * mult[i]; } else break; } } else //base 10 { printf("base value not supported (only base 16)\n"); } return val; } static int convert_raw_string(void *raw_data, int max_size, char raw_str[]) { int i = 0; int endian = 0; //0=le; 1=be int base = 16; int start_i = 0; int data_index = 0; uint8_t *data = (uint8_t *) raw_data; //convert raw_data string int length = strlen(raw_str); //check endianess if((length > 4) && raw_str[start_i] == '(' && raw_str[start_i+3] == ')') { if (isalpha(raw_str[start_i+1]) && isalpha(raw_str[start_i+2]) && toupper(raw_str[start_i+1]) == 'B' && toupper(raw_str[start_i+2]) == 'E') { endian = 1; } start_i = 4; } if((length > start_i + 1) && raw_str[start_i] == '0' && isalpha(raw_str[start_i+1]) && (toupper(raw_str[start_i+1]) == 'X')) { //hex base = 16; start_i += 2; } else { //we assume value data is in hex format printf("Assuming hex value (base 16)\n"); base = 16; } char str[2]; for(i=start_i; i 0) { //convert from big endian to little endian data = raw_inv(data, data_index); } // size in bytes return (data_index); } CResult get_control_list (CHandle handle, CControl **controls, unsigned int *count) { CResult ret; unsigned int req_size = 0, buffer_size = 0, local_count = 0; assert(*controls == NULL); do { // Allocate the required memory if(*controls) free(*controls); if(req_size) { // No allocation the first time *controls = (CControl *)malloc(req_size); if(*controls == NULL) { ret = C_NO_MEMORY; goto done; } buffer_size = req_size; } // Try to enumerate. If the buffer is not large enough, the required // size is returned. ret = c_enum_controls(handle, *controls, &req_size, &local_count); if(ret != C_SUCCESS && ret != C_BUFFER_TOO_SMALL) goto done; } while(buffer_size < req_size); if(count) *count = local_count; done: if(ret) { if(*controls) free(*controls); *controls = NULL; } return ret; } CControlId get_control_id (CHandle handle, const char *name) { CControlId id = 0; CResult res; unsigned int count = 0; CControl *controls = NULL; assert(name); // Retrieve the control list res = get_control_list(handle, &controls, &count); if(res) goto done; // Look for a control with the given name and return its ID for(int i = 0; i < count; i++) { CControl *control = &controls[i]; if(strcasecmp(name, control->name) == 0) { id = control->id; goto done; } } done: if(controls) free(controls); return id; } int parse_control_value (const char *string, CControlValue *value) { assert(string); assert(value); if(strcasecmp(string, "true") == 0 || strcasecmp(string, "on") == 0 || strcasecmp(string, "yes") == 0) { value->value = 1; return 0; } else if(strcasecmp(string, "false") == 0 || strcasecmp(string, "off") == 0 || strcasecmp(string, "no") == 0) { value->value = 0; return 0; } value->value = atoi(string); return 0; } int parse_raw_control_value (char *string, CControlValue *value) { assert(string); assert(value); value->type = CC_TYPE_RAW; /* hex format: * 1/2 chars => 1 byte e.g. 0xF = 0x0F * 3/4 chars => 2 bytes e.g. 0xFFF = 0x0FFF */ value->raw.size = strlen(string)/2 + 1; //at most length/2 + 1 value->raw.data = malloc(value->raw.size); //get the real value value->raw.size = convert_raw_string(value->raw.data, value->raw.size, string); return (value->raw.size); } libwebcam-src-0.2.4/uvcdynctrl/CMakeLists.txt0000644000175000017500000000673612234547770020235 0ustar paulopaulo# # GENERAL # # Require CMake 2.6 because of the Debian packaging. cmake_minimum_required (VERSION 2.6) project (UVCDYNCTRL) # # TARGETS # add_executable (uvcdynctrl main.c controls.c cmdline.c) set_target_properties (uvcdynctrl PROPERTIES VERSION 0.2.4) if (NOT DYNCTRL_DATA_DIR) set_target_properties (uvcdynctrl PROPERTIES DATA_DIR "${CMAKE_INSTALL_PREFIX}/share/uvcdynctrl") else (NOT DYNCTRL_DATA_DIR) set_target_properties (uvcdynctrl PROPERTIES DATA_DIR ${DYNCTRL_DATA_DIR}) endif (NOT DYNCTRL_DATA_DIR) # # SPECIAL FILES # # gengetopt for command line parsing if (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmdline.c" AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmdline.h") message("** Command line parser source files not found. Creating gengetopt rules ...") # Check if gengetopt is installed find_program(GENGETOPT gengetopt) if (NOT GENGETOPT) message(FATAL_ERROR "Unable to find gengetopt") endif (NOT GENGETOPT) add_custom_command ( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/cmdline.c ${CMAKE_CURRENT_SOURCE_DIR}/cmdline.h COMMAND gengetopt -i ${CMAKE_CURRENT_SOURCE_DIR}/uvcdynctrl.ggo --output-dir ${CMAKE_CURRENT_SOURCE_DIR} --unamed-opts=VALUES DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/uvcdynctrl.ggo COMMENT "Generating getopt parser code (cmdline.*) ..." VERBATIM ) endif (NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmdline.c" AND NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/cmdline.h") # config.h # Note how we define HAVE_CONFIG_H. This will let gengetopt pick up # the VERSION constant from config.h. get_target_property (UVCDYNCTRL_VERSION uvcdynctrl VERSION) get_target_property (UVCDYNCTRL_DATA_DIR uvcdynctrl DATA_DIR) configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config.h) add_definitions (-DHAVE_CONFIG_H) #create man pages execute_process ( COMMAND sh -c "rm -f ${CMAKE_CURRENT_BINARY_DIR}/*.gz; cp ${CMAKE_CURRENT_SOURCE_DIR}/uvcdynctrl.1_ ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl.1; cp ${CMAKE_CURRENT_SOURCE_DIR}/uvcdynctrl.1_ ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl-${UVCDYNCTRL_VERSION}.1; gzip --best ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl-${UVCDYNCTRL_VERSION}.1; gzip --best ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl.1;" RESULT_VARIABLE MAN_BUILD_RESULT ) if (MAN_BUILD_RESULT) message(ERROR " Unable to build man pages") else (MAN_BUILD_RESULT) message("** created man pages") endif (MAN_BUILD_RESULT) # # COMPILATION AND LINKING # include_directories (../common/include) include_directories (${CMAKE_CURRENT_BINARY_DIR}) link_directories (${LIBWEBCAM_BINARY_DIR}/webcam) target_link_libraries (uvcdynctrl webcam) # Compiler flags set_target_properties (uvcdynctrl PROPERTIES COMPILE_FLAGS "--std=gnu99 -Wall" ) # # INSTALLATION # # uvcdynctrl binary message("** Installation directory for uvcdynctrl: ${CMAKE_INSTALL_PREFIX}/bin") install ( TARGETS uvcdynctrl RUNTIME DESTINATION bin COMPONENT UVCDYNCTRL ) # udev rules, script, and data # Default permissions for DIRECTORY files: rw-r--r-- # Default permissions for PROGRAMS files: rwxr-xr-x # Note that having absolute paths here requires CPACK_SET_DESTDIR to be set to "ON". install ( FILES udev/rules/80-uvcdynctrl.rules DESTINATION /lib/udev/rules.d ) install ( PROGRAMS udev/scripts/uvcdynctrl DESTINATION /lib/udev ) install ( DIRECTORY data DESTINATION ${UVCDYNCTRL_DATA_DIR} PATTERN ".git" EXCLUDE ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl.1.gz ${CMAKE_CURRENT_BINARY_DIR}/uvcdynctrl-${UVCDYNCTRL_VERSION}.1.gz DESTINATION share/man/man1 ) libwebcam-src-0.2.4/uvcdynctrl/genincludes.sh0000755000175000017500000000014712234547770020322 0ustar paulopaulo#!/bin/sh xsltproc --output ../../Common/include/dynctrl-logitech.h include.xsl data/046d/logitech.xml libwebcam-src-0.2.4/uvcdynctrl/uvcdynctrl.ggo0000644000175000017500000000274012234547770020357 0ustar paulopaulo# GNU Gengetopt input file for uvcdynctrl # Program information # Note that we don't set the version here. We retrieve the version from # the VERSION constant in config.h. package "uvcdynctrl" #version "0.0" purpose "Manage dynamic controls in uvcvideo" # Action options (device independent) option "list" l "List available cameras" optional option "import" i "Import dynamic controls from an XML file" string typestr="filename" optional # Options option "verbose" v "Enable verbose output" flag off option "device" d "Specify the device to use" string typestr="devicename" optional default="video0" # Action options (device dependent) option "clist" c "List available controls" optional option "get" g "Retrieve the current control value" string typestr="control" optional option "get_raw" G "Retrieve the current raw control value" string typestr="unit_id:selector" optional option "set" s "Set a new control value\n(For negative values: -s 'My Control' -- -42)" string typestr="control" optional option "set_raw" S "Set a new raw control value\n(value is a hex string of control size,\ndefault is little endian use '(BE)' prefix to change:\n-S 13:1 0x01100c or -S 13:1 '(BE)0x0c1001' ))" string typestr="control" optional option "formats" f "List available frame formats" optional option "load" L "Load device controls state from a file" string typestr="filename" optional option "save" W "Save device controls state to a file" string typestr="filename" optionallibwebcam-src-0.2.4/uvcdynctrl/udev/0000755000175000017500000000000012234547770016424 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/udev/rules/0000755000175000017500000000000012234547770017556 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/udev/rules/80-uvcdynctrl.rules0000644000175000017500000000117312234547770023256 0ustar paulopaulo################################################################################################### # Rules for adding dynamic UVC extension unit controls to UVC devices. # # Note that the DRIVERS clause only works in newer versions of udev. For older versions the clause # never matches, making the script a no-op. # udev versions confirmed to work: 141 (Ubuntu 9.04), 142 (Ubuntu 9.10) # udev versions confirmed not to work: 117 (Ubuntu 8.04) ################################################################################################### ACTION=="add", SUBSYSTEM=="video4linux", DRIVERS=="uvcvideo", RUN+="/lib/udev/uvcdynctrl" libwebcam-src-0.2.4/uvcdynctrl/udev/scripts/0000755000175000017500000000000012234547770020113 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/udev/scripts/uvcdynctrl0000755000175000017500000000523712234547770022245 0ustar paulopaulo#!/bin/sh ################################################################################################### # udev helper script for UVC devices to support dynamic controls. # # Version: 0.2 # # Note that version 0.2 no longer works with older versions of udev. This script should be # compatible with udev >= 141. # Also check 80-uvcdynctrl.rules for more information. ################################################################################################### # Constants version=0.3 # Run-time configuration debug=1 uvcdynctrlpath=uvcdynctrl # Determine log destination if [ "$debug" != 0 ]; then logfile=/var/log/uvcdynctrl-udev.log else logfile=/dev/null fi # Write log header echo >> $logfile echo "==============================================================================" >> $logfile echo "uvcdynctrl script version $version running from '$0'" >> $logfile echo "Triggered at `date`" >> $logfile echo >> $logfile set >> $logfile echo >> $logfile # Check for the udev version and bail out if it's too old if [ -z "$ID_VENDOR_ID" ]; then echo "ERROR: The ID_VENDOR_ID variable is not defined. You are probably using an older version of udev. Please upgrade to udev >= 141 or use version 0.1 of this script." >> $logfile exit 2 fi # Extract the VID and PID vid=$ID_VENDOR_ID pid=$ID_MODEL_ID echo "VID of new device: '$vid'" >> $logfile echo "PID of new device: '$pid'" >> $logfile if [ -z $vid ]; then echo "ERROR: Unable to extract USB VID." >> $logfile exit 3 fi # Check whether the device is managed by the UVC driver if [ "$ID_USB_DRIVER" != "uvcvideo" ]; then echo "ERROR: Device is not handled by uvcvideo but by '$ID_USB_DRIVER'." >> $logfile if [ "$ID_USB_DRIVER" = "usb" ]; then echo "Note: There is a known problem for older versions of the UVC driver where the physical device path reported by udev ('/sys$PHYSDEVPATH' in this case) points to the USB device instead of the USB interface. For these versions of the UVC driver dynamic controls are not supported anyway. Please update your uvcvideo driver to the latest version if you know that this device is a UVC device." >> $logfile fi exit 4 fi #uvcdynctrl handles the data path internally # if we want to set device specific configuration we should use xmlpath/VID/PID.xml format # if PID.xml is not found all xml files inside xmlpath/VID will be imported # Path is handled internaly by uvcdynctrl ( usage: uvcdynctrl --addctrl=vid[:pid] ), pid is optional cmd="$uvcdynctrlpath -d $DEVNAME --addctrl=$vid:$pid" echo "Executing command: '$cmd'" >> $logfile $cmd >> $logfile 2>&1 # Write log footer echo "==============================================================================" >> $logfile echo >> $logfile libwebcam-src-0.2.4/uvcdynctrl/controls.h0000644000175000017500000000225312234547770017477 0ustar paulopaulo/* * uvcdynctrl - Manage dynamic controls in uvcvideo * * * Copyright (c) 2006-2007 Logitech. * * This file is part of uvcdynctrl. * * uvcdynctrl is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * uvcdynctrl 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 uvcdynctrl. If not, see . */ #ifndef LV_CONTROLS_H #define LV_CONTROLS_H #include extern CControlId get_control_id (CHandle handle, const char *name); extern CResult get_control_list (CHandle handle, CControl **controls, unsigned int *count); extern int parse_control_value (const char *string, CControlValue *value); extern int parse_raw_control_value (char *string, CControlValue *value); #endif /* LV_CONTROLS_H */ libwebcam-src-0.2.4/uvcdynctrl/uvcdynctrl.1_0000644000175000017500000000356612234547770020111 0ustar paulopaulo.\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.36. .TH UVCDYNCTRL 1 "7" "Aug 2013" "uvcdynctrl 0.2.3" "User Commands" .SH NAME uvcdynctrl\-0.2.3 \- libwebcam command line tool .SH SYNOPSIS .B uvcdynctrl [\fIOPTIONS\fR]... [\fIVALUES\fR]... .SH DESCRIPTION uvcdynctrl 0.2.3 .PP Manage dynamic controls in uvcvideo .TP \fB\-h\fR, \fB\-\-help\fR Print full help and exit .TP \fB\-V\fR, \fB\-\-version\fR Print version and exit .TP \fB\-l\fR, \fB\-\-list\fR List available cameras .TP \fB\-i\fR, \fB\-\-import\fR=\fIfilename\fR Import dynamic controls from an XML file .TP \fB\-a\fR, \fB\-\-addctrl\fR=\fIvid\fR Import dynamic controls for vid from default location .TP \fB\-v\fR, \fB\-\-verbose\fR Enable verbose output (default=off) .TP \fB\-d\fR, \fB\-\-device\fR=\fIdevicename\fR Specify the device to use (default=`video0') .TP \fB\-c\fR, \fB\-\-clist\fR List available controls .TP \fB\-g\fR, \fB\-\-get\fR=\fIcontrol\fR Retrieve the current control value \fB\-G\fR, \fB\-\-get_raw\fR=\fIunit_id:selector\fR Retrieve the current raw control value .TP \fB\-s\fR, \fB\-\-set\fR=\fIcontrol\fR Set a new control value (For negative values: \fB\-s\fR 'My Control' \fB\-\-\fR \fB\-42\fR) .TP \fB\-S\fR, \fB\-\-set_raw\fR=\fIunit_id:selector\fR Set a new raw control value (value is a hex string of control size, default is little endian use '(BE)' prefix to change: \-S 13:1 0x01100c or \-S 13:1 '(BE)0x0c1001' ) .TP \fB\-f\fR, \fB\-\-formats\fR List available frame formats .TP \fB\-W\fR, \fB\-\-save\fR=\fIfilename\fR Save device controls state to a file .TP \fB\-L\fR, \fB\-\-load\fR=\fIfilename\fR Load device controls state from a file .SH "SEE ALSO" The full documentation for .B uvcdynctrl is maintained as a Texinfo manual. If the .B info and .B uvcdynctrl programs are properly installed at your site, the command .IP .B info uvcdynctrl .PP should give you access to the complete manual. libwebcam-src-0.2.4/uvcdynctrl/data/0000755000175000017500000000000012234547770016372 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/data/046d/0000755000175000017500000000000012234547770017047 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/data/046d/logitech.xml0000755000175000017500000021213512234547770021376 0ustar paulopaulo 1.0 Martin Rubli, Logitech http://www.quickcamteam.net/ 0.32 Copyright (c) 2006-2010 Logitech 0.32 2013-03-27 - Added LED frequency V4L2 control mapping for V3 Logitech cameras 0.31 2013-02-25 - Added LED V4L2 control mapping for V3 Logitech cameras 0.30, 2010-07-30: - Added support for XU_TEST_PERIPHERAL_ACCESS_EXT_CONTROL. 0.29, 2010-07-26: - Updated the size of the XU_VIDEO_FW_ZOOM_CONTROL to be in sync with the latest specification. - Added support for XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL and XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL. 0.28, 2010-07-02: - Updated the size of the XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME to be in sync with the specification. 0.26, 2010-05-19: - Updated the size of several controls to be in sync with the latest version of the specification. This includes CXU_ENCODER_CONFIGURATION_CONTROL, CXU_RATE_CONTROL, CXXU_STATIC_CONTROL, CXU_DYNAMIC_CONTROL. 0.25, 2010-04-26: - Mark SET_CUR as supported for XU_EXTENDED_FIRMWARE_VERSION_CONTROL. This looks like a bug in the current specification because the control cannot be properly queried otherwise. - Mark GET_CUR instead of SET_CUR as supported for XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS to match latest specification. 0.24, 2010-04-24: - Updated the size of XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS to match latest implementation. 0.23, 2010-04-13: - Updated the size of CXU_ENCODER_VIDEO_FORMAT_CONTROL to be in sync with the latest version of the specification. 0.22, 2010-03-25: - Added support for XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS and XU_PERIPHERAL_CONTROL_SPEAKER. 0.21, 2010-02-24: - Commented out some potentially dangerous controls in the test and debug XU. 0.20, 2010-02-02: - Updated based on the H.264 Device Interface specification 0.9e from 2010-01-15. - Merged with wolverine.xml. This file is intended to be the master copy from which subsets can be extracted and published. - Added support for all FY11 extension unit controls. 0.17, 2008-10-17: - Mark the GET_CUR request as supported for the XU_MOTORCONTROL_FOCUS control. 0.16, 2008-03-07: - Updated the values of V4L2_CID_PAN_RELATIVE and V4L2_CID_PAN_RELATIVE to work with the latest UVC driver (those values will be part of kernels >= 2.6.26). - Support for two new controls defined by V4L2 starting from 2.6.26: V4L2_CID_PAN_RESET ('Pan Reset') and V4L2_CID_TILT_RESET ('Tilt reset'). 0.15, 2007-12-13: - Added a control to change the LED blink frequency. - Added the two controls required for enabling Bayer mode (Disable video processing and Raw bits per pixel). 0.14, 2007-11-19: - Fixed the bitmap indices which were off by one. 0.13, 2007-11-16: - Added focus motor control for cameras that support it (QuickCam Pro 9000, QuickCam Pro for Notebooks, QuickCam Orbit/Sphere AF). - Added the pan/tilt reset control for the QuickCam Orbit/Sphere series. - Added a control to change the LED mode. 0.12, 2007-11-02: - Initial release to the public UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 63610682-5070-49ab-b8cc-b3855e8d221f UVC_GUID_LOGITECH_VIDEO_PIPE_V1 63610682-5070-49ab-b8cc-b3855e8d2250 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 63610682-5070-49ab-b8cc-b3855e8d2256 UVC_GUID_LOGITECH_DEVICE_INFORMATION_V1 63610682-5070-49ab-b8cc-b3855e8d221e UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 69678EE4-410F-40db-A850-7420D7D8240E UVC_GUID_LOGITECH_VIDEO_PIPE_V3 49E40215-F434-47fe-B158-0E885023E51B UVC_GUID_LOGITECH_TEST_DEBUG_V3 1F5D4CA9-DE11-4487-840D-50933C8EC8D1 UVC_GUID_LOGITECH_PERIPHERAL FFE52D21-8030-4e2c-82D9-F587D00540BD UVC_GUID_LOGITECH_CODEC 9ACD00B6-DC4A-4bbd-BDF8-5FFBB0C0D366 UVC_GUID_LOGITECH_CODECEX 49C532A0-4F15-4cfc-908A-5BCE154B1CEA GUID_UVCX_H264_XU A29E7641-DE04-47E3-8B2B-F4341AFF003B XU_HW_CONTROL_LED1 1 XU_COLOR_PROCESSING_DISABLE 5 XU_RAW_DATA_BITS_PER_PIXEL 8 XU_MOTORCONTROL_PANTILT_RELATIVE 1 XU_MOTORCONTROL_PANTILT_RESET 2 XU_MOTORCONTROL_FOCUS 3 XU_FIRMWARE_VERSION_CONTROL 0x01 XU_FIRMWARE_CRC_CONTROL 0x02 XU_EEPROM_VERSION_CONTROL 0x03 XU_SENSOR_INFORMATION_CONTROL 0x04 XU_PROCESSOR_INFORMATION_CONTROL 0x05 XU_USB_INFORMATION_CONTROL 0x06 XU_LENS_FOV_CONTROL 0x09 XU_SENSOR_DIMENSION_CONTROL 0x0A XU_EXTENDED_FIRMWARE_VERSION_CONTROL 0x0B XU_VIDEO_COLOR_BOOST_CONTROL 0x01 XU_VIDEO_NATIVE_MODE_FORCED_CONTROL 0x02 XU_VIDEO_NATIVE_MODE_AUTO_CONTROL 0x03 XU_VIDEO_RIGHTLIGHT_MODE_CONTROL 0x04 XU_VIDEO_RIGHTLIGHT_ZOI_CONTROL 0x05 XU_VIDEO_FW_ZOOM_CONTROL 0x06 XU_VIDEO_DUAL_ISO_ENABLE_CONTROL 0x07 XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL 0x08 XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL 0x09 XU_TEST_TDE_MODE_CONTROL 0x0A XU_TEST_GAIN_CONTROL 0x0B XU_TEST_LOW_LIGHT_PRIORITY_CONTROL 0x0C XU_TEST_COLOR_PROCESSING_DISABLE_CONTROL 0x0D XU_TEST_PIXEL_DEFECT_CORRECTION_CONTROL 0x0E XU_TEST_LENS_SHADING_COMPENSATION_CONTROL 0x0F XU_TEST_GAMMA_CONTROL 0x10 XU_TEST_INTEGRATION_TIME_CONTROL 0x11 XU_TEST_RAW_DATA_BITS_PER_PIXEL_CONTROL 0x12 XU_PERIPHERALCONTROL_PANTILT_RELATIVE_CONTROL 0x01 XU_PERIPHERALCONTROL_PANTILT_MODE_CONTROL 0x02 XU_PERIPHERALCONTROL_MAXIMUM_RESOLUTION_SUPPORT_FOR_PANTILT_CONTROL 0x03 XU_PERIPHERALCONTROL_AF_MOTORCONTROL 0x04 XU_PERIPHERALCONTROL_AF_BLOB_CONTROL 0x05 XU_PERIPHERALCONTROL_AF_VCM_PARAMETERS 0x06 XU_PERIPHERALCONTROL_AF_STATUS 0x07 XU_PERIPHERALCONTROL_AF_THRESHOLDS 0x08 XU_PERIPHERALCONTROL_LED 0x09 XU_PERIPHERAL_CONTROL_PERIPHERAL_STATUS 0x0A XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME 0x0B XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS 0x0C XU_PERIPHERAL_CONTROL_SPEAKER 0x0D CXU_ENCODER_VIDEO_FORMAT_CONTROL 0x01 CXU_ENCODER_CONFIGURATION_CONTROL 0x02 CXU_RATE_CONTROL 0x03 CXU_FRAME_TYPE_CONTROL 0x04 CXU_CAMERA_DELAY 0x05 CXU_FILTER_CONTROL 0x06 UVCX_VIDEO_CONFIG_PROBE 0x01 UVCX_VIDEO_CONFIG_COMMIT 0x02 UVCX_RATE_CONTROL_MODE 0x03 UVCX_TEMPORAL_SCALE_MODE 0x04 UVCX_SPATIAL_SCALE_MODE 0x05 UVCX_SNR_SCALE_MODE 0x06 UVCX_LTR_BUFFER_SIZE_CONTROL 0x07 UVCX_LTR_PICTURE_CONTROL 0x08 UVCX_PICTURE_TYPE_CONTROL 0x09 UVCX_VERSION 0x0A UVCX_ENCODER_RESET 0x0B UVCX_FRAMERATE_CONFIG 0x0C UVCX_VIDEO_ADVANCE_CONFIG 0x0D UVCX_BITRATE_LAYERS 0x0E UVCX_QP_STEPS_LAYERS 0x0F CXXU_STATIC_CONTROL 0x01 CXXU_DYNAMIC_CONTROL 0x02 CXXU_ROI_CONTROL 0x03 V4L2_CID_USB_VID 0x0A046DF0 V4L2_CID_USB_PID 0x0A046DF1 V4L2_CID_USB_BCD 0x0A046DF2 V4L2_CID_USB_INFO 0x0A046DF3 V4L2_CID_PAN_RELATIVE 0x009A0904 V4L2_CID_TILT_RELATIVE 0x009A0905 V4L2_CID_PAN_RESET 0x009A0906 V4L2_CID_TILT_RESET 0x009A0907 V4L2_CID_FOCUS_ABSOLUTE 0x009A090A V4L2_CID_LED1_MODE 0x0A046D05 V4L2_CID_LED1_FREQUENCY 0x0A046D06 V4L2_CID_DISABLE_PROCESSING 0x0A046D71 V4L2_CID_RAW_BITS_PER_PIXEL 0x0A046D72 0x046d UVC_GUID_LOGITECH_VIDEO_PIPE_V1 XU_COLOR_PROCESSING_DISABLE 4 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Enable or disable the color processing pipeline within the camera. 0 = color processing enabled (default) 1 = color processing disabled UVC_GUID_LOGITECH_VIDEO_PIPE_V1 XU_RAW_DATA_BITS_PER_PIXEL 7 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Specify the number of bits per pixel for raw data. This value is only relevant if XU_COLOR_PROCESSING_DISABLE is set to 0. 0 = 8 bits per pixel (default) 1 = 10 bits per pixel UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 XU_HW_CONTROL_LED1 0 3 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Allows control over the state of the first LED. Bits 0 to 7 represent the LED mode. Currently, the following modes are available: - 0: Off. The LED is never illuminated, whether or not the device is streaming video. - 1: On. The LED is always illuminated, whether or not the device is streaming video. - 2: Blinking. The LED blinks, whether or not the device is streaming video. - 3: Auto. The LED is in control of the device. Typically this means that means that is is illuminated when streaming video and off when not streaming video. Bits 16 to 23 represent the LED frequency. The frequency value only influences the 'Blinking' mode. It is expressed in units of 0.05 Hz and sets the blink frequency f. The blink interval T = 1/f is defined as the time between two adjoining rising edges (or two adjoining falling edges). The following table illustrates the relation between the LED frequency value used in bits 16 to 23, the physical blink frequency, and the physical blink interval. +-------------------------------+------------------------+----------------------+ | Frequency value 20f [0.05 Hz] | Blink frequency f [Hz] | Blink interval T [s] | +-------------------------------+------------------------+----------------------+ | 1 | 0.05 | 20 | | 2 | 0.1 | 10 | | 10 | 0.5 | 2 | | 20 | 1 | 1 | | 50 | 2.5 | 0.4 | | 100 | 5 | 0.2 | +-------------------------------+------------------------+----------------------+ 0x046d 0x0809 0x0990 0x0991 0x0994 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_FOCUS 2 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_DEF Allows the control of focus motor movements for camera models that support mechanical focus. Bits 0 to 7 allow selection of the desired lens position. There are no physical units, instead, the focus range is spread over 256 logical units with 0 representing infinity focus and 255 being macro focus. 0x046d 0x08c2 0x08cc 0x0994 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_PANTILT_RELATIVE 0 4 SET_CUR GET_MIN GET_MAX GET_DEF Allows the control of pan/tilt motor movements for camera models that support mechanical pan/tilt. Bits 0 to 15 control pan, bits 16 to 31 control tilt. The unit of the pan/tilt values is 1/64th of a degree and the resolution is 1 degree. UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_PANTILT_RESET 1 1 SET_CUR GET_MIN GET_MAX GET_DEF Reset the pan/tilt motors to their original position for camera models that support mechanical pan/tilt. Setting bit 0 resets the pan position. Setting bit 1 resets the tilt position. Both bits can be set at the same time to reset both, pan and tilt, at the same time. 0x046d UVC_GUID_LOGITECH_DEVICE_INFORMATION_V1 XU_USB_INFORMATION_CONTROL 5 6 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_FIRMWARE_VERSION_CONTROL 0 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_FIRMWARE_CRC_CONTROL 1 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_EEPROM_VERSION_CONTROL 2 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_SENSOR_INFORMATION_CONTROL 3 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_PROCESSOR_INFORMATION_CONTROL 4 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_USB_INFORMATION_CONTROL 5 6 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_LENS_FOV_CONTROL 8 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_SENSOR_DIMENSION_CONTROL 9 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_EXTENDED_FIRMWARE_VERSION_CONTROL 10 5 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_COLOR_BOOST_CONTROL 0 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_NATIVE_MODE_FORCED_CONTROL 1 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_NATIVE_MODE_AUTO_CONTROL 2 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_RIGHTLIGHT_MODE_CONTROL 3 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_FW_ZOOM_CONTROL 5 2 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_DUAL_ISO_ENABLE_CONTROL 6 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL 7 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL 8 2 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_TDE_MODE_CONTROL 9 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_GAIN_CONTROL 10 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_LOW_LIGHT_PRIORITY_CONTROL 11 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_COLOR_PROCESSING_DISABLE_CONTROL 12 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_PIXEL_DEFECT_CORRECTION_CONTROL 13 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_LENS_SHADING_COMPENSATION_CONTROL 14 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_GAMMA_CONTROL 15 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_INTEGRATION_TIME_CONTROL 16 4 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_RAW_DATA_BITS_PER_PIXEL_CONTROL 17 1 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_PANTILT_RELATIVE_CONTROL 0 4 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_PANTILT_MODE_CONTROL 1 1 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_MAXIMUM_RESOLUTION_SUPPORT_FOR_PANTILT_CONTROL 2 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_MOTORCONTROL 3 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_VCM_PARAMETERS 5 10 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_STATUS 6 7 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_THRESHOLDS 7 4 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_LED 8 5 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_PERIPHERAL_STATUS 9 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME 10 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS 11 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_SPEAKER 12 4 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF GUID_UVCX_H264_XU UVCX_VIDEO_CONFIG_PROBE 0 46 GET_CUR SET_CUR GET_MIN GET_MAX GET_LEN GET_INFO GET_DEF GUID_UVCX_H264_XU UVCX_VIDEO_CONFIG_COMMIT 1 46 SET_CUR 0x046d 0x080c UVC_GUID_LOGITECH_CODEC CXU_ENCODER_VIDEO_FORMAT_CONTROL 0 10 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODEC CXU_ENCODER_CONFIGURATION_CONTROL 1 25 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODEC CXU_RATE_CONTROL 2 8 SET_CUR GET_CUR GET_MIN GET_MAX GET_DEF UVC_GUID_LOGITECH_CODEC CXU_FRAME_TYPE_CONTROL 3 1 SET_CUR UVC_GUID_LOGITECH_CODEC CXU_CAMERA_DELAY 4 2 GET_CUR UVC_GUID_LOGITECH_CODEC CXU_FILTER_CONTROL 5 2 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_STATIC_CONTROL 0 132 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_DYNAMIC_CONTROL 1 144 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_ROI_CONTROL 2 124 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Pan (relative) 16 0 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_PAN_RELATIVE V4L2_CTRL_TYPE_INTEGER Pan (relative) 16 0 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_PAN_RELATIVE V4L2_CTRL_TYPE_INTEGER Tilt (relative) 16 16 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_TILT_RELATIVE V4L2_CTRL_TYPE_INTEGER Tilt (relative) 16 16 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_TILT_RELATIVE V4L2_CTRL_TYPE_INTEGER Pan Reset 1 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_PAN_RESET V4L2_CTRL_TYPE_BUTTON Pan Reset 1 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_PAN_RESET V4L2_CTRL_TYPE_BUTTON Tilt Reset 1 1 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_TILT_RESET V4L2_CTRL_TYPE_BUTTON Tilt Reset 1 1 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_TILT_RESET V4L2_CTRL_TYPE_BUTTON Focus 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_FOCUS_ABSOLUTE V4L2_CTRL_TYPE_INTEGER LED1 Mode 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_MODE V4L2_CTRL_TYPE_MENU LED1 Frequency 8 16 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_FREQUENCY V4L2_CTRL_TYPE_INTEGER Disable video processing 8 0 UVC_CTRL_DATA_TYPE_BOOLEAN V4L2_CID_DISABLE_PROCESSING V4L2_CTRL_TYPE_BOOLEAN Raw bits per pixel 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_RAW_BITS_PER_PIXEL V4L2_CTRL_TYPE_INTEGER Raw bits per pixel 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_RAW_BITS_PER_PIXEL V4L2_CTRL_TYPE_INTEGER LED1 Mode 2 8 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_MODE V4L2_CTRL_TYPE_MENU LED1 Frequency 8 24 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_FREQUENCY V4L2_CTRL_TYPE_INTEGER libwebcam-src-0.2.4/uvcdynctrl/data/046d/logitech.xml~0000755000175000017500000021777512234547770021613 0ustar paulopaulo 1.0 Martin Rubli, Logitech http://www.quickcamteam.net/ 0.32 Copyright (c) 2006-2010 Logitech 0.32 2013-03-27 - Added LED frequency V4L2 control mapping for V3 Logitech cameras 0.31 2013-02-25 - Added LED V4L2 control mapping for V3 Logitech cameras 0.30, 2010-07-30: - Added support for XU_TEST_PERIPHERAL_ACCESS_EXT_CONTROL. 0.29, 2010-07-26: - Updated the size of the XU_VIDEO_FW_ZOOM_CONTROL to be in sync with the latest specification. - Added support for XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL and XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL. 0.28, 2010-07-02: - Updated the size of the XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME to be in sync with the specification. 0.26, 2010-05-19: - Updated the size of several controls to be in sync with the latest version of the specification. This includes CXU_ENCODER_CONFIGURATION_CONTROL, CXU_RATE_CONTROL, CXXU_STATIC_CONTROL, CXU_DYNAMIC_CONTROL. 0.25, 2010-04-26: - Mark SET_CUR as supported for XU_EXTENDED_FIRMWARE_VERSION_CONTROL. This looks like a bug in the current specification because the control cannot be properly queried otherwise. - Mark GET_CUR instead of SET_CUR as supported for XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS to match latest specification. 0.24, 2010-04-24: - Updated the size of XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS to match latest implementation. 0.23, 2010-04-13: - Updated the size of CXU_ENCODER_VIDEO_FORMAT_CONTROL to be in sync with the latest version of the specification. 0.22, 2010-03-25: - Added support for XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS and XU_PERIPHERAL_CONTROL_SPEAKER. 0.21, 2010-02-24: - Commented out some potentially dangerous controls in the test and debug XU. 0.20, 2010-02-02: - Updated based on the H.264 Device Interface specification 0.9e from 2010-01-15. - Merged with wolverine.xml. This file is intended to be the master copy from which subsets can be extracted and published. - Added support for all FY11 extension unit controls. 0.17, 2008-10-17: - Mark the GET_CUR request as supported for the XU_MOTORCONTROL_FOCUS control. 0.16, 2008-03-07: - Updated the values of V4L2_CID_PAN_RELATIVE and V4L2_CID_PAN_RELATIVE to work with the latest UVC driver (those values will be part of kernels >= 2.6.26). - Support for two new controls defined by V4L2 starting from 2.6.26: V4L2_CID_PAN_RESET ('Pan Reset') and V4L2_CID_TILT_RESET ('Tilt reset'). 0.15, 2007-12-13: - Added a control to change the LED blink frequency. - Added the two controls required for enabling Bayer mode (Disable video processing and Raw bits per pixel). 0.14, 2007-11-19: - Fixed the bitmap indices which were off by one. 0.13, 2007-11-16: - Added focus motor control for cameras that support it (QuickCam Pro 9000, QuickCam Pro for Notebooks, QuickCam Orbit/Sphere AF). - Added the pan/tilt reset control for the QuickCam Orbit/Sphere series. - Added a control to change the LED mode. 0.12, 2007-11-02: - Initial release to the public UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 63610682-5070-49ab-b8cc-b3855e8d221f UVC_GUID_LOGITECH_VIDEO_PIPE_V1 63610682-5070-49ab-b8cc-b3855e8d2250 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 63610682-5070-49ab-b8cc-b3855e8d2256 UVC_GUID_LOGITECH_DEVICE_INFORMATION_V1 63610682-5070-49ab-b8cc-b3855e8d221e UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 69678EE4-410F-40db-A850-7420D7D8240E UVC_GUID_LOGITECH_VIDEO_PIPE_V3 49E40215-F434-47fe-B158-0E885023E51B UVC_GUID_LOGITECH_TEST_DEBUG_V3 1F5D4CA9-DE11-4487-840D-50933C8EC8D1 UVC_GUID_LOGITECH_PERIPHERAL FFE52D21-8030-4e2c-82D9-F587D00540BD UVC_GUID_LOGITECH_CODEC 9ACD00B6-DC4A-4bbd-BDF8-5FFBB0C0D366 UVC_GUID_LOGITECH_CODECEX 49C532A0-4F15-4cfc-908A-5BCE154B1CEA GUID_UVCX_H264_XU A29E7641-DE04-47E3-8B2B-F4341AFF003B XU_HW_CONTROL_LED1 1 XU_COLOR_PROCESSING_DISABLE 5 XU_RAW_DATA_BITS_PER_PIXEL 8 XU_MOTORCONTROL_PANTILT_RELATIVE 1 XU_MOTORCONTROL_PANTILT_RESET 2 XU_MOTORCONTROL_FOCUS 3 XU_FIRMWARE_VERSION_CONTROL 0x01 XU_FIRMWARE_CRC_CONTROL 0x02 XU_EEPROM_VERSION_CONTROL 0x03 XU_SENSOR_INFORMATION_CONTROL 0x04 XU_PROCESSOR_INFORMATION_CONTROL 0x05 XU_USB_INFORMATION_CONTROL 0x06 XU_LENS_FOV_CONTROL 0x09 XU_SENSOR_DIMENSION_CONTROL 0x0A XU_EXTENDED_FIRMWARE_VERSION_CONTROL 0x0B XU_VIDEO_COLOR_BOOST_CONTROL 0x01 XU_VIDEO_NATIVE_MODE_FORCED_CONTROL 0x02 XU_VIDEO_NATIVE_MODE_AUTO_CONTROL 0x03 XU_VIDEO_RIGHTLIGHT_MODE_CONTROL 0x04 XU_VIDEO_RIGHTLIGHT_ZOI_CONTROL 0x05 XU_VIDEO_FW_ZOOM_CONTROL 0x06 XU_VIDEO_DUAL_ISO_ENABLE_CONTROL 0x07 XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL 0x08 XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL 0x09 XU_TEST_TDE_MODE_CONTROL 0x0A XU_TEST_GAIN_CONTROL 0x0B XU_TEST_LOW_LIGHT_PRIORITY_CONTROL 0x0C XU_TEST_COLOR_PROCESSING_DISABLE_CONTROL 0x0D XU_TEST_PIXEL_DEFECT_CORRECTION_CONTROL 0x0E XU_TEST_LENS_SHADING_COMPENSATION_CONTROL 0x0F XU_TEST_GAMMA_CONTROL 0x10 XU_TEST_INTEGRATION_TIME_CONTROL 0x11 XU_TEST_RAW_DATA_BITS_PER_PIXEL_CONTROL 0x12 XU_PERIPHERALCONTROL_PANTILT_RELATIVE_CONTROL 0x01 XU_PERIPHERALCONTROL_PANTILT_MODE_CONTROL 0x02 XU_PERIPHERALCONTROL_MAXIMUM_RESOLUTION_SUPPORT_FOR_PANTILT_CONTROL 0x03 XU_PERIPHERALCONTROL_AF_MOTORCONTROL 0x04 XU_PERIPHERALCONTROL_AF_BLOB_CONTROL 0x05 XU_PERIPHERALCONTROL_AF_VCM_PARAMETERS 0x06 XU_PERIPHERALCONTROL_AF_STATUS 0x07 XU_PERIPHERALCONTROL_AF_THRESHOLDS 0x08 XU_PERIPHERALCONTROL_LED 0x09 XU_PERIPHERAL_CONTROL_PERIPHERAL_STATUS 0x0A XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME 0x0B XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS 0x0C XU_PERIPHERAL_CONTROL_SPEAKER 0x0D CXU_ENCODER_VIDEO_FORMAT_CONTROL 0x01 CXU_ENCODER_CONFIGURATION_CONTROL 0x02 CXU_RATE_CONTROL 0x03 CXU_FRAME_TYPE_CONTROL 0x04 CXU_CAMERA_DELAY 0x05 CXU_FILTER_CONTROL 0x06 UVCX_VIDEO_CONFIG_PROBE 0x01 UVCX_VIDEO_CONFIG_COMMIT 0x02 UVCX_RATE_CONTROL_MODE 0x03 UVCX_TEMPORAL_SCALE_MODE 0x04 UVCX_SPATIAL_SCALE_MODE 0x05 UVCX_SNR_SCALE_MODE 0x06 UVCX_LTR_BUFFER_SIZE_CONTROL 0x07 UVCX_LTR_PICTURE_CONTROL 0x08 UVCX_PICTURE_TYPE_CONTROL 0x09 UVCX_VERSION 0x0A UVCX_ENCODER_RESET 0x0B UVCX_FRAMERATE_CONFIG 0x0C UVCX_VIDEO_ADVANCE_CONFIG 0x0D UVCX_BITRATE_LAYERS 0x0E UVCX_QP_STEPS_LAYERS 0x0F CXXU_STATIC_CONTROL 0x01 CXXU_DYNAMIC_CONTROL 0x02 CXXU_ROI_CONTROL 0x03 V4L2_CID_USB_VID 0x0A046DF0 V4L2_CID_USB_PID 0x0A046DF1 V4L2_CID_USB_BCD 0x0A046DF2 V4L2_CID_USB_INFO 0x0A046DF3 V4L2_CID_PAN_RELATIVE 0x009A0904 V4L2_CID_TILT_RELATIVE 0x009A0905 V4L2_CID_PAN_RESET 0x009A0906 V4L2_CID_TILT_RESET 0x009A0907 V4L2_CID_FOCUS_ABSOLUTE 0x009A090A V4L2_CID_LED1_MODE 0x0A046D05 V4L2_CID_LED1_FREQUENCY 0x0A046D06 V4L2_CID_DISABLE_PROCESSING 0x0A046D71 V4L2_CID_RAW_BITS_PER_PIXEL 0x0A046D72 V4L2_UVC_H264_PRB_FRAME_INTERVAL 0x0A046D50 V4L2_UVC_H264_PRB_BIT_RATE 0x0A046D51 V4L2_UVC_H264_PRB_HINTS 0x0A046D52 V4L2_UVC_H264_PRB_CONFIG_INDEX 0x0A046D53 V4L2_UVC_H264_PRB_WIDTH 0x0A046D54 V4L2_UVC_H264_PRB_HEIGHT 0x0A046D55 V4L2_UVC_H264_PRB_SLICE_UNITS 0x0A046D56 V4L2_UVC_H264_PRB_SLICE_MODE 0x0A046D57 V4L2_UVC_H264_PRB_PROFILE 0x0A046D58 V4L2_UVC_H264_PRB_IFRAME_PERIOD 0x0A046D59 V4L2_UVC_H264_PRB_ESTIMATED_VIDEO_DELAY 0x0A046D5A V4L2_UVC_H264_PRB_USAGE_TYPE 0x0A046D5B V4L2_UVC_H264_PRB_RATE_CONTROL_MODE 0x0A046D5C V4L2_UVC_H264_PRB_TEMPORAL_SCALE_MODE 0x0A046D5D V4L2_UVC_H264_PRB_SPATIAL_SCALE_MODE 0x0A046D5E V4L2_UVC_H264_PRB_SNR_SCALE_MODE 0x0A046D5F V4L2_UVC_H264_PRB_STREAM_MUX_OPTION 0x0A046D60 V4L2_UVC_H264_PRB_STREAM_FORMAT 0x0A046D61 V4L2_UVC_H264_PRB_ENTROPY_CABAC 0x0A046D62 V4L2_UVC_H264_PRB_TIMESTAMP 0x0A046D63 V4L2_UVC_H264_PRB_NUM_OF_REORDER_FRAMES 0x0A046D64 V4L2_UVC_H264_PRB_PREVIEW_FLIPPED 0x0A046D65 V4L2_UVC_H264_PRB_VIEW 0x0A046D66 V4L2_UVC_H264_PRB_STREAM_ID 0x0A046D67 V4L2_UVC_H264_PRB_SPATIAL_LAYER_RATIO 0x0A046D68 V4L2_UVC_H264_PRB_LEAKY_BUCKET_SIZE 0x0A046D69 0x046d UVC_GUID_LOGITECH_VIDEO_PIPE_V1 XU_COLOR_PROCESSING_DISABLE 4 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Enable or disable the color processing pipeline within the camera. 0 = color processing enabled (default) 1 = color processing disabled UVC_GUID_LOGITECH_VIDEO_PIPE_V1 XU_RAW_DATA_BITS_PER_PIXEL 7 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Specify the number of bits per pixel for raw data. This value is only relevant if XU_COLOR_PROCESSING_DISABLE is set to 0. 0 = 8 bits per pixel (default) 1 = 10 bits per pixel UVC_GUID_LOGITECH_USER_HW_CONTROL_V1 XU_HW_CONTROL_LED1 0 3 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Allows control over the state of the first LED. Bits 0 to 7 represent the LED mode. Currently, the following modes are available: - 0: Off. The LED is never illuminated, whether or not the device is streaming video. - 1: On. The LED is always illuminated, whether or not the device is streaming video. - 2: Blinking. The LED blinks, whether or not the device is streaming video. - 3: Auto. The LED is in control of the device. Typically this means that means that is is illuminated when streaming video and off when not streaming video. Bits 16 to 23 represent the LED frequency. The frequency value only influences the 'Blinking' mode. It is expressed in units of 0.05 Hz and sets the blink frequency f. The blink interval T = 1/f is defined as the time between two adjoining rising edges (or two adjoining falling edges). The following table illustrates the relation between the LED frequency value used in bits 16 to 23, the physical blink frequency, and the physical blink interval. +-------------------------------+------------------------+----------------------+ | Frequency value 20f [0.05 Hz] | Blink frequency f [Hz] | Blink interval T [s] | +-------------------------------+------------------------+----------------------+ | 1 | 0.05 | 20 | | 2 | 0.1 | 10 | | 10 | 0.5 | 2 | | 20 | 1 | 1 | | 50 | 2.5 | 0.4 | | 100 | 5 | 0.2 | +-------------------------------+------------------------+----------------------+ 0x046d 0x0809 0x0990 0x0991 0x0994 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_FOCUS 2 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_DEF Allows the control of focus motor movements for camera models that support mechanical focus. Bits 0 to 7 allow selection of the desired lens position. There are no physical units, instead, the focus range is spread over 256 logical units with 0 representing infinity focus and 255 being macro focus. 0x046d 0x08c2 0x08cc 0x0994 UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_PANTILT_RELATIVE 0 4 SET_CUR GET_MIN GET_MAX GET_DEF Allows the control of pan/tilt motor movements for camera models that support mechanical pan/tilt. Bits 0 to 15 control pan, bits 16 to 31 control tilt. The unit of the pan/tilt values is 1/64th of a degree and the resolution is 1 degree. UVC_GUID_LOGITECH_MOTOR_CONTROL_V1 XU_MOTORCONTROL_PANTILT_RESET 1 1 SET_CUR GET_MIN GET_MAX GET_DEF Reset the pan/tilt motors to their original position for camera models that support mechanical pan/tilt. Setting bit 0 resets the pan position. Setting bit 1 resets the tilt position. Both bits can be set at the same time to reset both, pan and tilt, at the same time. 0x046d UVC_GUID_LOGITECH_DEVICE_INFORMATION_V1 XU_USB_INFORMATION_CONTROL 5 6 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_FIRMWARE_VERSION_CONTROL 0 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_FIRMWARE_CRC_CONTROL 1 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_EEPROM_VERSION_CONTROL 2 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_SENSOR_INFORMATION_CONTROL 3 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_PROCESSOR_INFORMATION_CONTROL 4 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_USB_INFORMATION_CONTROL 5 6 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_LENS_FOV_CONTROL 8 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_SENSOR_DIMENSION_CONTROL 9 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_DEVICE_INFORMATION_V3 XU_EXTENDED_FIRMWARE_VERSION_CONTROL 10 5 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_COLOR_BOOST_CONTROL 0 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_NATIVE_MODE_FORCED_CONTROL 1 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_NATIVE_MODE_AUTO_CONTROL 2 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_RIGHTLIGHT_MODE_CONTROL 3 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_FW_ZOOM_CONTROL 5 2 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_DUAL_ISO_ENABLE_CONTROL 6 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_SENSOR_CROPPING_DIMENSION_CONTROL 7 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_VIDEO_PIPE_V3 XU_VIDEO_MJPEG_RESYNC_MARKER_CONTROL 8 2 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_TDE_MODE_CONTROL 9 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_GAIN_CONTROL 10 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_LOW_LIGHT_PRIORITY_CONTROL 11 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_COLOR_PROCESSING_DISABLE_CONTROL 12 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_PIXEL_DEFECT_CORRECTION_CONTROL 13 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_LENS_SHADING_COMPENSATION_CONTROL 14 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_GAMMA_CONTROL 15 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_INTEGRATION_TIME_CONTROL 16 4 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_TEST_DEBUG_V3 XU_TEST_RAW_DATA_BITS_PER_PIXEL_CONTROL 17 1 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_PANTILT_RELATIVE_CONTROL 0 4 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_PANTILT_MODE_CONTROL 1 1 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_MAXIMUM_RESOLUTION_SUPPORT_FOR_PANTILT_CONTROL 2 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_MOTORCONTROL 3 6 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_VCM_PARAMETERS 5 10 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_STATUS 6 7 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_AF_THRESHOLDS 7 4 SET_CUR GET_CUR UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERALCONTROL_LED 8 5 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_PERIPHERAL_STATUS 9 2 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_SPEAKER_VOLUME 10 1 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_DEVICE_CODEC_STATUS 11 4 GET_CUR GET_MIN GET_MAX GET_RES GET_DEF UVC_GUID_LOGITECH_PERIPHERAL XU_PERIPHERAL_CONTROL_SPEAKER 12 4 SET_CUR GET_MIN GET_MAX GET_RES GET_DEF GUID_UVCX_H264_XU UVCX_VIDEO_CONFIG_PROBE 0 46 GET_CUR SET_CUR GET_MIN GET_MAX GET_LEN GET_INFO GET_DEF GUID_UVCX_H264_XU UVCX_VIDEO_CONFIG_COMMIT 1 46 SET_CUR 0x046d 0x080c UVC_GUID_LOGITECH_CODEC CXU_ENCODER_VIDEO_FORMAT_CONTROL 0 10 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODEC CXU_ENCODER_CONFIGURATION_CONTROL 1 25 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODEC CXU_RATE_CONTROL 2 8 SET_CUR GET_CUR GET_MIN GET_MAX GET_DEF UVC_GUID_LOGITECH_CODEC CXU_FRAME_TYPE_CONTROL 3 1 SET_CUR UVC_GUID_LOGITECH_CODEC CXU_CAMERA_DELAY 4 2 GET_CUR UVC_GUID_LOGITECH_CODEC CXU_FILTER_CONTROL 5 2 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_STATIC_CONTROL 0 132 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_DYNAMIC_CONTROL 1 144 SET_CUR GET_CUR GET_DEF UVC_GUID_LOGITECH_CODECEX CXXU_ROI_CONTROL 2 124 SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Pan (relative) 16 0 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_PAN_RELATIVE V4L2_CTRL_TYPE_INTEGER Pan (relative) 16 0 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_PAN_RELATIVE V4L2_CTRL_TYPE_INTEGER Tilt (relative) 16 16 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_TILT_RELATIVE V4L2_CTRL_TYPE_INTEGER Tilt (relative) 16 16 UVC_CTRL_DATA_TYPE_SIGNED V4L2_CID_TILT_RELATIVE V4L2_CTRL_TYPE_INTEGER Pan Reset 1 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_PAN_RESET V4L2_CTRL_TYPE_BUTTON Pan Reset 1 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_PAN_RESET V4L2_CTRL_TYPE_BUTTON Tilt Reset 1 1 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_TILT_RESET V4L2_CTRL_TYPE_BUTTON Tilt Reset 1 1 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_TILT_RESET V4L2_CTRL_TYPE_BUTTON Focus 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_FOCUS_ABSOLUTE V4L2_CTRL_TYPE_INTEGER LED1 Mode 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_MODE V4L2_CTRL_TYPE_MENU LED1 Frequency 8 16 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_FREQUENCY V4L2_CTRL_TYPE_INTEGER Disable video processing 8 0 UVC_CTRL_DATA_TYPE_BOOLEAN V4L2_CID_DISABLE_PROCESSING V4L2_CTRL_TYPE_BOOLEAN Raw bits per pixel 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_RAW_BITS_PER_PIXEL V4L2_CTRL_TYPE_INTEGER Raw bits per pixel 8 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_RAW_BITS_PER_PIXEL V4L2_CTRL_TYPE_INTEGER LED1 Mode 2 8 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_MODE V4L2_CTRL_TYPE_MENU LED1 Frequency 8 24 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_LED1_FREQUENCY V4L2_CTRL_TYPE_INTEGER libwebcam-src-0.2.4/uvcdynctrl/data/a0c8/0000755000175000017500000000000012234547770017125 5ustar paulopaulolibwebcam-src-0.2.4/uvcdynctrl/data/a0c8/sisdop.xml0000755000175000017500000000525712234547770021164 0ustar paulopaulo 1.0 Manav Gautama bandwidthcrunch@gmail.com 0.10 Copyright (c) Manav Gautama 2012 Initial Import of the vimicro based SIS DOP camera for enabling XU LED flash UVC_GUID_SIS_LED_HW_CONTROL 5dc717a9-1941-da11-ae0e-000d56ac7b4c XU_HW_CONTROL_FLASH 4 V4L2_CID_FLASH_MODE 0xb030 V4L2_CID_FLASH_FREQUENCY 0xb031 0xa0c8 3460 UVC_GUID_SIS_LED_HW_CONTROL XU_HW_CONTROL_FLASH 2 4` SET_CUR GET_CUR GET_MIN GET_MAX GET_RES GET_DEF Allows control over the state of the first LED. Not much else information available at this time. LED2 Mode 4 0 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_FLASH_MODE V4L2_CTRL_TYPE_MENU LED2 Frequency 8 16 UVC_CTRL_DATA_TYPE_UNSIGNED V4L2_CID_FLASH_FREQUENCY V4L2_CTRL_TYPE_INTEGER libwebcam-src-0.2.4/uvcdynctrl/include.xsl0000644000175000017500000000577412234547770017651 0ustar paulopaulo /* Start constants */ /* End constants */ /* * UVC dynamic control mapping header file * * This file has been dynamically generated using the include.xsl XSLT * transform stylesheet from a dynamic control mapping configuration file. * */ * Version: * Author: * Contact: * Revision: * * #ifndef #define #define { \ 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x, \ 0x, 0x, 0x, 0x, 0x, 0x, 0x, 0x \ } /* Unknown constant type '' encountered */ /* #define */ #endif libwebcam-src-0.2.4/uvcdynctrl/cmdline.h0000644000175000017500000002327512234547770017256 0ustar paulopaulo/** @file cmdline.h * @brief The header file for the command line option parser * generated by GNU Gengetopt version 2.22 * http://www.gnu.org/software/gengetopt. * DO NOT modify this file, since it can be overwritten * @author GNU Gengetopt by Lorenzo Bettini */ #ifndef CMDLINE_H #define CMDLINE_H /* If we use autoconf. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include /* for FILE */ #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ #ifndef CMDLINE_PARSER_PACKAGE /** @brief the program name */ #define CMDLINE_PARSER_PACKAGE "uvcdynctrl" #endif #ifndef CMDLINE_PARSER_VERSION /** @brief the program version */ #define CMDLINE_PARSER_VERSION VERSION #endif /** @brief Where the command line options are stored */ struct gengetopt_args_info { const char *help_help; /**< @brief Print help and exit help description. */ const char *version_help; /**< @brief Print version and exit help description. */ const char *list_help; /**< @brief List available cameras help description. */ char * import_arg; /**< @brief Import dynamic controls from an XML file. */ char * import_orig; /**< @brief Import dynamic controls from an XML file original value given at command line. */ const char *import_help; /**< @brief Import dynamic controls from an XML file help description. */ char * addctrl_arg; /**< @brief Import dynamic controls for vid from default location. */ char * addctrl_orig; /**< @brief Import dynamic controls for vid given at command line from default location. */ const char *addctrl_help; /**< @brief Enable addctrl help description. */ int verbose_flag; /**< @brief Enable verbose output (default=off). */ const char *verbose_help; /**< @brief Enable verbose output help description. */ char * device_arg; /**< @brief Specify the device to use (default='video0'). */ char * device_orig; /**< @brief Specify the device to use original value given at command line. */ const char *device_help; /**< @brief Specify the device to use help description. */ const char *clist_help; /**< @brief List available controls help description. */ char * get_arg; /**< @brief Retrieve the current control value. */ char * get_orig; /**< @brief Retrieve the current control value original value given at command line. */ const char *get_help; /**< @brief Retrieve the current control value help description. */ char * get_raw_arg; /**< @brief Retrieve the current raw control value. */ char * get_raw_orig; /**< @brief Retrieve the current raw control value- original value given at command line. */ const char *get_raw_help; /**< @brief Retrieve the current raw control value- help description. */ char * set_arg; /**< @brief Set a new control value\n(For negative values: -s 'My Control' -- -42). */ char * set_orig; /**< @brief Set a new control value\n(For negative values: -s 'My Control' -- -42) original value given at command line. */ char * set_raw_arg; /**< @brief Set the current raw control value. */ char * set_raw_orig; /**< @brief Set the current raw control value- original value given at command line. */ const char *set_raw_help; /**< @brief Set the current raw control value- help description. */ const char *set_help; /**< @brief Set a new control value\n(For negative values: -s 'My Control' -- -42) help description. */ const char *formats_help; /**< @brief List available frame formats help description. */ char * save_ctrl_arg; /**< @brief save controls to a file. */ char * save_ctrl_orig; /**< @brief save controls to file original value given at command line. */ const char *save_ctrl_help; /**< @brief save ctrl help description. */ char * load_ctrl_arg; /**< @brief load controls to a file. */ char * load_ctrl_orig; /**< @brief load controls to file original value given at command line. */ const char *load_ctrl_help; /**< @brief load ctrl help description. */ unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int list_given ; /**< @brief Whether list was given. */ unsigned int import_given ; /**< @brief Whether import was given. */ unsigned int addctrl_given ; /**< @brief Whether addctrl was given. */ unsigned int verbose_given ; /**< @brief Whether verbose was given. */ unsigned int device_given ; /**< @brief Whether device was given. */ unsigned int clist_given ; /**< @brief Whether clist was given. */ unsigned int get_given ; /**< @brief Whether get was given. */ unsigned int get_raw_given ; /**< @brief Whether get_raw was given. */ unsigned int set_given ; /**< @brief Whether set was given. */ unsigned int set_raw_given ; /**< @brief Whether set_raw was given. */ unsigned int formats_given ; /**< @brief Whether formats was given. */ unsigned int save_ctrl_given; /**< @brief Whether save ctrl was given. */ unsigned int load_ctrl_given; /**< @brief Whether load ctrl was given. */ char **inputs ; /**< @brief unamed options (options without names) */ unsigned inputs_num ; /**< @brief unamed options number */ } ; /** @brief The additional parameters to pass to parser functions */ struct cmdline_parser_params { int override; /**< @brief whether to override possibly already present options (default 0) */ int initialize; /**< @brief whether to initialize the option structure gengetopt_args_info (default 1) */ int check_required; /**< @brief whether to check that all required options were provided (default 1) */ int check_ambiguity; /**< @brief whether to check for options already specified in the option structure gengetopt_args_info (default 0) */ int print_errors; /**< @brief whether getopt_long should print an error message for a bad option (default 1) */ } ; /** @brief the purpose string of the program */ extern const char *gengetopt_args_info_purpose; /** @brief the usage string of the program */ extern const char *gengetopt_args_info_usage; /** @brief all the lines making the help output */ extern const char *gengetopt_args_info_help[]; /** * The command line parser * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info); /** * The command line parser (version with additional parameters - deprecated) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param override whether to override possibly already present options * @param initialize whether to initialize the option structure my_args_info * @param check_required whether to check that all required options were provided * @return 0 if everything went fine, NON 0 if an error took place * @deprecated use cmdline_parser_ext() instead */ int cmdline_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required); /** * The command line parser (version with additional parameters) * @param argc the number of command line options * @param argv the command line options * @param args_info the structure where option information will be stored * @param params additional parameters for the parser * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info, struct cmdline_parser_params *params); /** * Save the contents of the option struct into an already open FILE stream. * @param outfile the stream where to dump options * @param args_info the option struct to dump * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info); /** * Save the contents of the option struct into a (text) file. * This file can be read by the config file parser (if generated by gengetopt) * @param filename the file where to save * @param args_info the option struct to save * @return 0 if everything went fine, NON 0 if an error took place */ int cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info); /** * Print the help */ void cmdline_parser_print_help(void); /** * Print the version */ void cmdline_parser_print_version(void); /** * Initializes all the fields a cmdline_parser_params structure * to their default values * @param params the structure to initialize */ void cmdline_parser_params_init(struct cmdline_parser_params *params); /** * Allocates dynamically a cmdline_parser_params structure and initializes * all its fields to their default values * @return the created and initialized cmdline_parser_params structure */ struct cmdline_parser_params *cmdline_parser_params_create(void); /** * Initializes the passed gengetopt_args_info structure's fields * (also set default values for options that have a default) * @param args_info the structure to initialize */ void cmdline_parser_init (struct gengetopt_args_info *args_info); /** * Deallocates the string fields of the gengetopt_args_info structure * (but does not deallocate the structure itself) * @param args_info the structure to deallocate */ void cmdline_parser_free (struct gengetopt_args_info *args_info); /** * Checks that all the required options were specified * @param args_info the structure to check * @param prog_name the name of the program that will be used to print * possible errors * @return */ int cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* CMDLINE_H */ libwebcam-src-0.2.4/uvcdynctrl/README0000644000175000017500000001025112234547770016340 0ustar paulopaulouvcdynctrl - Manage dynamic controls in uvcvideo ================================================ Introduction ------------ For an introduction to dynamic controls you should first read the dynctrl.txt that comes with the Linux UVC driver. You can find it here: http://svn.berlios.de/svnroot/repos/linux-uvc/linux-uvc/trunk/ The combination of uvcdynctrl and libwebcam allows to manage these dynamic controls from user space. While libwebcam contains the actual implementation, uvcdynctrl presents a command line interface to do so. Currently only the UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls are supported. Support for the remaining functions is planned. The documentation is not really complete at this time. In particular, the XML format that is used to describe dynamic controls is undocumented except for a sample file and an XML schema. This will be fixed very soon. uvcdynctrl is designed to eventually work together with udev, so that control mappings are automatically added whenever a UVC device is plugged and a matching dynamic controls configuration file is available. Apart from the dynamic controls feature uvcdynctrl also provides a few handy functions that illustrate the power of libwebcam. Check out the built-in command line help for details. udev support ------------ The uvcdynctrl package contains udev support, i.e. a udev rule file and a helper script that calls uvcdynctrl to import the appropriate XML file when a camera is connected. If you run "make install" as root, the following udev-related files will be installed: /etc/udev/rules.d/80-uvcdynctrl.rules (rule for V4L devices) /lib/udev/uvcdynctrl (helper script to launch uvcdynctrl) /etc/udev/data/046d/logitech.xml (dynamic control configuration for Logitech devices) These paths are hardcoded in uvcdynctrl/CMakeLists.txt and have only been tested on Ubuntu with udev versions >= 141. If your distribution uses different paths, you need to make changes to that file before running the installation. If you're using an older version of udev you may want to try the udev scripts of an older version which is tagged as "0.1.3-pre" and can be found here: http://svn.quickcamteam.net/svn/qct/webcam-tools/tags/0.1.3-pre/ Please send us feedback (preferrably through the QuickCam Team forum, see the main README file for the link) about the udev functionality, especially on non-Ubuntu systems. If you want to debug the uvcdynctrl udev script, you can find some basic debug output in /var/log/uvcdynctrl-udev.log. Change log ---------- 0.3 (under development): - Reorganized the directory layout and build system. - Exit with a non-zero code if errors occur while getting or setting controls. - Improved udev support (udev >= 141 is required now). 0.2 (2008-01-29): - Experimental support for udev (support script and rules). - Added a new option -f or --formats to list a device's frame format list (pixel formats, frame sizes, and frame intervals). - Make use of the improved error message reporting in libwebcam. - Added support for displaying processing statistics in verbose mode. - Support for the new informational messages (dynctrl). - Added a hint to the quick help on how to set negative control values. - Fix: Import (-i) no longer needs a valid device to be specified (or the default video0 to be present). 0.1: Initial release Building, questions, and feedback --------------------------------- Please see the README file in the top level directory for building instructions and how to contact the developers. Copyright and license --------------------- Copyright (c) 2006-2010 Logitech. uvcdynctrl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. uvcdynctrl 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 uvcdynctrl. If not, see . libwebcam-src-0.2.4/uvcdynctrl/main.c0000644000175000017500000006466212234547770016567 0ustar paulopaulo/* * uvcdynctrl - Manage dynamic controls in uvcvideo * * * Copyright (c) 2006-2010 Logitech. * * This file is part of uvcdynctrl. * * uvcdynctrl is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * uvcdynctrl 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 uvcdynctrl. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define __user #include #include "config.h" #include "cmdline.h" #include "controls.h" static struct gengetopt_args_info args_info; #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) #define HAS_VERBOSE() (args_info.verbose_given) static void print_handle_error (CHandle hDevice, const char *error, CResult res) { if((int)res < 0) { printf("ERROR: %s.\n", error); } else { char *text = c_get_handle_error_text(hDevice, res); if(text) { printf("ERROR: %s: %s. (Code: %d)\n", error, text, res); free(text); } else { printf("ERROR: %s: Unknown error (Code: %d)\n", error, res); } } } static void print_error (const char *error, CResult res) { print_handle_error(0, error, res); } static const char *get_control_type (CControlType type) { switch(type) { case CC_TYPE_RAW: return "Raw"; case CC_TYPE_BOOLEAN: return "Boolean"; case CC_TYPE_CHOICE: return "Choice"; case CC_TYPE_BYTE: return "Byte"; case CC_TYPE_WORD: return "Word"; case CC_TYPE_DWORD: return "Dword"; case CC_TYPE_BUTTON: return "Button"; default: return ""; } } // Note: The caller must free the buffer obtained from this function. static char * get_control_flags (CControlFlags flags) { const char *delimiter = ", "; const char *names[] = { "CAN_READ", "CAN_WRITE", "CAN_NOTIFY", "", "", "", "", "", "IS_CUSTOM", "IS_RELATIVE", "IS_ACTION", }; char buffer[14 * ARRAY_SIZE(names)]; // 14 = maximum name length + strlen(delimiter) memset(buffer, 0, sizeof(buffer)); for(int i = 0; i < ARRAY_SIZE(names); i++) { if(flags & (1 << i)) { strcat(buffer, names[i]); if(flags >= (1 << (i + 1))) strcat(buffer, delimiter); } } return strdup(buffer); } // Note: The caller must free the buffer obtained from this function. static char * get_control_choices (CControl *control) { const char *delimiter = ", "; char *buffer; unsigned int req_size = 0; unsigned int count = control->choices.count; for(int i = 0; i < count; i++) { req_size += 1 + strlen(control->choices.list[i].name) + 1 + 12; if(i < count - 1) req_size += strlen(delimiter); } buffer = (char *)malloc(req_size + 1); memset(buffer, 0, req_size + 1); for(int i = 0; i < control->choices.count; i++) { char index_buffer[13]; sprintf(index_buffer, "[%u]", control->choices.list[i].index); strcat(buffer, "'"); strcat(buffer, control->choices.list[i].name); strcat(buffer, "'"); strcat(buffer, index_buffer); if(i < count - 1) strcat(buffer, delimiter); } return buffer; } static void print_control (CControl *control) { if(HAS_VERBOSE()) { char *flags = get_control_flags(control->flags); printf(" %s\n ID : 0x%08x,\n Type : %s,\n Flags : { %s },\n", control->name, control->id, get_control_type(control->type), flags); if(control->type == CC_TYPE_CHOICE) { char *choices = get_control_choices(control); printf(" Values : { %s },\n Default : %d\n", choices, control->def.value); free(choices); } else { printf(" Values : [ %d .. %d, step size: %d ],\n Default : %d\n", control->min.value, control->max.value, control->step.value, control->def.value); } free(flags); } else { printf(" %s\n", control->name); } } static void print_device (CDevice *device) { if(HAS_VERBOSE()) { printf(" %s %s [%s, %s]\n", device->shortName, device->name, device->driver, device->location); } else { printf(" %s %s\n", device->shortName, device->name); } } static int file_exists (char * fileName) { int result = access (fileName, F_OK); /* File found */ if ( result == 0 ) { return 1; } return 0; } static CResult save_controls (CHandle hDevice, const char* filename) { int ret = C_SUCCESS; ret = c_save_controls (hDevice, filename); return ret; } static CResult load_controls (CHandle hDevice, const char* filename) { int ret = C_SUCCESS; ret = c_load_controls (hDevice, filename); return ret; } static CResult list_controls (CHandle hDevice) { CResult ret; unsigned int count = 0; CControl *controls = NULL; // Retrieve the control list ret = get_control_list(hDevice, &controls, &count); if(ret) goto done; if(count == 0) { printf("No controls found.\n"); goto done; } // Print a list of all available controls for(int i = 0; i < count; i++) { CControl *control = &controls[i]; print_control(control); } done: if(controls) free(controls); if(ret) print_handle_error(hDevice, "Unable to retrieve device list", ret); return ret; } static CResult list_frame_intervals (CHandle hDevice, CPixelFormat *pixelformat, CFrameSize *framesize) { CResult ret = C_SUCCESS; CFrameInterval *intervals = NULL; unsigned int size = 0, count = 0; ret = c_enum_frame_intervals(hDevice, pixelformat, framesize, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { intervals = (CFrameInterval *)malloc(size); ret = c_enum_frame_intervals(hDevice, pixelformat, framesize, intervals, &size, &count); if(ret) { print_handle_error(hDevice, "Unable to enumerate frame intervals", ret); goto done; } // Display all frame intervals if(HAS_VERBOSE()) { // Verbose: one line per interval for(unsigned int i = 0; i < count; i++) { CFrameInterval *fival = &intervals[i]; if(fival->type == CF_INTERVAL_DISCRETE) { printf(" Frame interval: %u/%u [s]\n", fival->n, fival->d); } else if(fival->type == CF_INTERVAL_CONTINUOUS) { printf(" Frame intervals: %u/%u - %u/%u [s] (continuous)\n", fival->min_n, fival->min_d, fival->max_n, fival->max_d ); } else if(fival->type == CF_INTERVAL_STEPWISE) { printf(" Frame intervals: %u/%u - %u/%u [s] (in steps of %u/%u [s])\n", fival->min_n, fival->min_d, fival->max_n, fival->max_d, fival->step_n, fival->step_d ); } else { print_handle_error(hDevice, "Unrecognized frame interval type", -1); } } } else { // Determine how concise we can be int simple = 1; for(unsigned int i = 0; i < count; i++) { if(intervals[i].type != CF_INTERVAL_DISCRETE || intervals[i].n != 1) { simple = 0; break; } } // Not verbose if(simple) { printf(" Frame rates: "); for(unsigned int i = 0; i < count; i++) { printf("%u%s", intervals[i].d, i < count - 1 ? ", " : ""); } printf("\n"); } else { printf(" Frame intervals: "); for(unsigned int i = 0; i < count; i++) { CFrameInterval *fival = &intervals[i]; if(fival->type == CF_INTERVAL_DISCRETE) { printf("%u/%u", fival->n, fival->d); } else if(fival->type == CF_INTERVAL_CONTINUOUS) { printf("%u/%u - %u/%u", fival->min_n, fival->min_d, fival->max_n, fival->max_d ); } else if(fival->type == CF_INTERVAL_STEPWISE) { printf("%u/%u - %u/%u (%u/%u)", fival->min_n, fival->min_d, fival->max_n, fival->max_d, fival->step_n, fival->step_d ); } else { printf(""); } if(i < count - 1) printf(", "); } printf("\n"); } } } else if(ret == C_SUCCESS) { printf("No frame intervals found.\n"); } else { print_handle_error(hDevice, "No frame intervals found", ret); } done: if(intervals) free(intervals); return ret; } static CResult list_frame_sizes (CHandle hDevice, CPixelFormat *pixelformat) { CResult ret = C_SUCCESS; CFrameSize *sizes = NULL; unsigned int size = 0, count = 0; ret = c_enum_frame_sizes(hDevice, pixelformat, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { sizes = (CFrameSize *)malloc(size); ret = c_enum_frame_sizes(hDevice, pixelformat, sizes, &size, &count); if(ret) { print_handle_error(hDevice, "Unable to enumerate frame sizes", ret); goto done; } for(unsigned int i = 0; i < count; i++) { CFrameSize *fsize = &sizes[i]; if(fsize->type == CF_SIZE_DISCRETE) { printf(" Frame size: %ux%u\n", fsize->width, fsize->height); list_frame_intervals(hDevice, pixelformat, fsize); } else if(fsize->type == CF_SIZE_CONTINUOUS) { printf(" Frame sizes: %ux%u - %ux%u (continuous)\n" " Will not display frame intervals.\n", fsize->min_width, fsize->min_height, fsize->max_width, fsize->max_height ); } else if(fsize->type == CF_SIZE_STEPWISE) { printf(" Frame sizes: %ux%u - %ux%u (in steps of width = %u, height = %u)\n" " Will not display frame intervals.\n", fsize->min_width, fsize->min_height, fsize->max_width, fsize->max_height, fsize->step_width, fsize->step_height ); } else { print_handle_error(hDevice, "Unrecognized frame size type", -1); } } } else if(ret == C_SUCCESS) { printf("No frame sizes found.\n"); } else { print_handle_error(hDevice, "No frame sizes found", ret); } done: if(sizes) free(sizes); return ret; } static CResult list_frame_formats (CHandle hDevice) { CResult ret = C_SUCCESS; CPixelFormat *formats = NULL; unsigned int size = 0, count = 0; ret = c_enum_pixel_formats(hDevice, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { formats = (CPixelFormat *)malloc(size); ret = c_enum_pixel_formats(hDevice, formats, &size, &count); if(ret) { print_handle_error(hDevice, "Unable to enumerate pixel formats", ret); goto done; } for(unsigned int i = 0; i < count; i++) { CPixelFormat *format = &formats[i]; printf("Pixel format: %s (%s%s%s)\n", format->fourcc, format->name, format->mimeType ? "; MIME type: " : "", format->mimeType ? format->mimeType : "" ); list_frame_sizes(hDevice, format); } } else if(ret == C_SUCCESS) { printf("No pixel formats found.\n"); } else { print_handle_error(hDevice, "No pixel formats found", ret); } done: if(formats) free(formats); return ret; } static CResult list_entities (CDevice *device) { assert(device != NULL); int device_index = -1; if(sscanf(device->shortName, "video%u", &device_index) != 1) return C_INVALID_ARG; char media_path[32] = { 0 }; sprintf(media_path, "/dev/media%u", device_index); //check for device node if(file_exists(media_path)) printf(" Media controller device: %s\n", media_path); else { printf(" Media controller device %s doesn't exist\n", media_path); return C_INVALID_DEVICE; } int mcdev = open(media_path, O_RDWR); if(mcdev == -1) { printf("ERROR: Unable to open media controller device '%s': %s (Error: %d)\n", media_path, strerror(errno), errno); return C_INVALID_DEVICE; } int r = 0; struct media_entity_desc entity; memset(&entity, 0, sizeof(entity)); entity.id = 1; while((r = ioctl(mcdev, MEDIA_IOC_ENUM_ENTITIES, &entity)) == 0) { printf( " Entity %u: %s. Type: %u, Revision: %u, Flags: %u, Group-id: %u, Pads: %u, Links: %u\n", entity.id, entity.name, entity.type, entity.revision, entity.flags, entity.group_id, entity.pads, entity.links ); switch(entity.type & MEDIA_ENT_TYPE_MASK) { case MEDIA_ENT_T_DEVNODE: printf(" Device node\n"); switch(entity.type & MEDIA_ENT_SUBTYPE_MASK) { case MEDIA_ENT_T_DEVNODE_V4L: printf(" Node: v4l: { major: %u, minor: %u }\n", entity.v4l.major, entity.v4l.minor); break; case MEDIA_ENT_T_DEVNODE_FB: printf(" Node: fb: { major: %u, minor: %u }\n", entity.fb.major, entity.fb.minor); break; case MEDIA_ENT_T_DEVNODE_ALSA: printf(" Node: alsa: {card: %u, device: %u, subdevice: %u}\n", entity.alsa.card, entity.alsa.device, entity.alsa.subdevice); break; case MEDIA_ENT_T_DEVNODE_DVB: printf(" Node: dvb: %u\n", entity.dvb); break; } break; case MEDIA_ENT_T_V4L2_SUBDEV: printf(" Subdevice: "); switch(entity.type & MEDIA_ENT_SUBTYPE_MASK) { case MEDIA_ENT_T_V4L2_SUBDEV_SENSOR: printf(" Sensor\n"); break; case MEDIA_ENT_T_V4L2_SUBDEV_FLASH: printf(" Flash\n"); break; case MEDIA_ENT_T_V4L2_SUBDEV_LENS: printf(" Lens\n"); break; } break; } struct media_links_enum links; memset(&links, 0, sizeof(links)); links.entity = entity.id; links.pads = (struct media_pad_desc *)calloc(entity.pads, sizeof(struct media_pad_desc)); links.links = (struct media_link_desc *)calloc(entity.links, sizeof(struct media_link_desc)); r = ioctl(mcdev, MEDIA_IOC_ENUM_LINKS, &links); if(r == 0) { for(int i = 0; i < entity.pads; i++) { struct media_pad_desc *pelem = &links.pads[i]; printf( " Entity: %u, Pad %u, Flags: %u\n", pelem->entity, pelem->index, pelem->flags ); } for(int i = 0; i < entity.links; i++) { struct media_link_desc *lelem = &links.links[i]; printf( " Out link: Source pad { Entity: %u, Index: %u, Flags: %u } => " "Sink pad { Entity: %u, Index: %u, Flags: %u }\n", lelem->source.entity, lelem->source.index, lelem->source.flags, lelem->sink.entity, lelem->sink.index, lelem->sink.flags ); } } else { printf("ERROR: Unable to enumerate links for entity %u: %s (Error: %d)\n", entity.id, strerror(errno), errno); } free(links.links); links.links = NULL; free(links.pads); links.pads = NULL; entity.id++; } close(mcdev); return C_SUCCESS; } static CResult list_devices () { CResult ret; unsigned int req_size = 0, buffer_size = 0, count = 0; CDevice *devices = NULL; printf("Listing available devices:\n"); do { // Allocate the required memory if(devices) free(devices); if(req_size) { // No allocation the first time devices = (CDevice *)malloc(req_size); if(devices == NULL) return C_NO_MEMORY; buffer_size = req_size; } // Try to enumerate. If the buffer is not large enough, the required // size is returned. ret = c_enum_devices(devices, &req_size, &count); if(ret != C_SUCCESS && ret != C_BUFFER_TOO_SMALL) goto done; } while(buffer_size < req_size); if(count == 0) { printf("No devices found.\n"); goto done; } // Print a list of all available devices for(int i = 0; i < count; i++) { CDevice *device = &devices[i]; print_device(device); ret = list_entities(device); if(ret != C_SUCCESS && ret != C_INVALID_ARG) { print_error("Unable to list device entities", ret); ret = C_SUCCESS; } } done: if(devices) free(devices); if(ret) print_error("Unable to retrieve device list", ret); return ret; } /* * join path strings */ static char* path_cat (const char * str1, char * str2) { size_t str1_len = strlen (str1); size_t str2_len = strlen (str2); int nc; if ((str1[str1_len] != '/') && (str2[0] != '/')) nc = 2; else nc = 1; char * result; result = malloc ((str1_len + str2_len + nc) * sizeof * result); strcpy (result, str1); int i, j; i = str1_len; if (nc > 1) result[i] = '/'; i++; for (j = 0; ((i <(str1_len + str2_len + (nc-1))) && (j d_type == DT_DIR) && (fnmatch("[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]", dp->d_name, 0) == 0)) { if( strcasecmp(vid, dp->d_name) != 0) { /*doesn't match - clean up and move to the next entry*/ continue; } char *tmp = path_cat (dir_path, dp->d_name); printf("found dir: %s \n", dp->d_name); DIR * subdir = opendir(tmp); while ((sdp = readdir(subdir)) != NULL) { if( fnmatch("*.xml", sdp->d_name, 0) == 0 ) { file_list[nf-1] = path_cat (tmp, sdp->d_name); printf("found: %s \n", file_list[nf-1]); nf++; file_list = realloc(file_list,nf*sizeof(file_list)); file_list[nf-1] = NULL; } } closedir(subdir); free (tmp); tmp = NULL; } } if(!file_list[0]) printf("Could not find %s entry\n", vid); closedir (dir); return(file_list); } static CResult add_control_mappings(CHandle hDevice, const char *filename) { CResult res; CDynctrlInfo info = { 0 }; info.flags = CD_REPORT_ERRORS; if(HAS_VERBOSE()) info.flags |= CD_RETRIEVE_META_INFO; printf("Importing dynamic controls from file %s.\n", filename); if (hDevice) res = c_add_control_mappings(hDevice, filename, &info); else res = c_add_control_mappings_from_file(filename, &info); if(res) print_error("Unable to import dynamic controls", res); // Print meta information if we're in verbose mode if(res == C_SUCCESS && HAS_VERBOSE()) { printf( "Available meta information:\n" " File format: %d.%d\n" " Author: %s\n" " Contact: %s\n" " Copyright: %s\n" " Revision: %d.%d\n", info.meta.version.major, info.meta.version.minor, info.meta.author ? info.meta.author : "(unknown)", info.meta.contact ? info.meta.contact : "(unknown)", info.meta.copyright ? info.meta.copyright : "(unknown)", info.meta.revision.major, info.meta.revision.minor ); } // Print errors if(info.message_count) { for(int i = 0; i < info.message_count; i++) { CDynctrlMessage *msg = &info.messages[i]; const char *severity = "message"; switch(msg->severity) { case CD_SEVERITY_ERROR: severity = "error"; break; case CD_SEVERITY_WARNING: severity = "warning"; break; case CD_SEVERITY_INFO: severity = "info"; break; } if(msg->line && msg->col) { printf("%s:%d:%d: %s: %s\n", filename, msg->line, msg->col, severity, msg->text); } else if(msg->line) { printf("%s:%d: %s: %s\n", filename, msg->line, severity, msg->text); } else { printf("%s: %s: %s\n", filename, severity, msg->text); } } } // Print processing statistics if we're in verbose mode if(HAS_VERBOSE()) { printf( "Processing statistics:\n" " %u constants processed (%u failed, %u successful)\n" " %u controls processed (%u failed, %u successful)\n" " %u mappings processed (%u failed, %u successful)\n", info.stats.constants.successful + info.stats.constants.failed, info.stats.constants.successful, info.stats.constants.failed, info.stats.controls.successful + info.stats.controls.failed, info.stats.controls.successful, info.stats.controls.failed, info.stats.mappings.successful + info.stats.mappings.failed, info.stats.mappings.successful, info.stats.mappings.failed ); } if(info.messages) free(info.messages); if(info.meta.author) free(info.meta.author); if(info.meta.contact) free(info.meta.contact); if(info.meta.author) free(info.meta.copyright); return res; } int main (int argc, char **argv) { CHandle handle = 0; CResult res = C_SUCCESS; // Parse the command line if(cmdline_parser(argc, argv, &args_info) != 0) exit(1); // Display help if no arguments were specified if(argc == 1) { cmdline_parser_print_help(); exit(0); } res = c_init(); if(res) goto done; // Open the device if (!args_info.list_given && (!args_info.import_given || args_info.device_given)) { handle = c_open_device(args_info.device_arg); if(!handle) { print_error("Unable to open device", -1); res = C_INVALID_DEVICE; goto done; } } // List devices if(args_info.list_given) { res = list_devices(); goto done; } // Import dynamic controls from XML file else if(args_info.import_given) { res = add_control_mappings(handle, args_info.import_arg); goto done; } // Import dynamic controls from XML files at default location if(args_info.addctrl_given) { // list all xml files at default data/vid dir int nf=0; char vid[5]; char pid[5]; short pid_set = 0; if(fnmatch("[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]", args_info.addctrl_arg, 0)) { if(fnmatch("[[:xdigit:]][[:xdigit:]][[:xdigit:]][[:xdigit:]]", args_info.addctrl_arg, 0)) { printf("%s invalid: set at least a valid vid value, :pid is optional\n", args_info.addctrl_arg); goto done; } else { /*extract vid and reset pid*/ int c = 0; for (c = 0; c < 4; c++) { vid[c] = args_info.addctrl_arg[c]; pid[c] = 0; } vid[4] = '\0'; pid[4] = '\0'; } } else { /*extract vid and pid*/ int c = 0; for (c = 0; c < 4; c++) { vid[c] = args_info.addctrl_arg[c]; pid[c] = args_info.addctrl_arg[c+5]; } vid[4] = '\0'; pid[4] = '\0'; pid_set = 1; /*flag pid.xml check*/ //printf("vid:%s pid:%s\n", vid, pid); } /* get xml file list from DATA_DIR/vid/ */ char **xml_files = get_filename (DATA_DIR, vid); /*check for pid.xml*/ char fname[9]; strcpy(fname, pid); strcat(fname,".xml"); if(pid_set) { pid_set = 0; /*reset*/ nf=0; while (xml_files[nf] != NULL) { if ( strcasecmp(fname, xml_files[nf]) == 0) pid_set = 1; /*file exists so flag it*/ nf++; } } /*parse xml files*/ nf = 0; while (xml_files[nf] != NULL) { /* if pid was set and pid.xml exists parse it*/ if(pid_set) { if ((strcasecmp(fname, xml_files[nf]) == 0)) { printf ( "Parsing: %s \n", xml_files[nf]); res = add_control_mappings(handle, xml_files[nf]); } } else /* parse all xml files inside vid dir */ { printf ( "Parsing: %s \n", xml_files[nf]); res = add_control_mappings(handle, xml_files[nf]); } free(xml_files[nf]); xml_files[nf]=NULL; nf++; } free(xml_files); goto done; } // List frame formats if(args_info.formats_given) { printf("Listing available frame formats for device %s:\n", args_info.device_arg); res = list_frame_formats(handle); } // List controls else if(args_info.clist_given) { printf("Listing available controls for device %s:\n", args_info.device_arg); res = list_controls(handle); } // Retrieve control value else if(args_info.get_given) { CControlValue value; // Resolve the control Id CControlId controlId = get_control_id(handle, args_info.get_arg); if(!controlId) { res = 1; print_handle_error(handle, "Unknown control specified", -1); goto done; } // Retrieve the control value res = c_get_control(handle, controlId, &value); if(res) { print_handle_error(handle, "Unable to retrieve control value", res); goto done; } printf("%d\n", value.value); } // Retrieve raw control value else if(args_info.get_raw_given) { //scan input uint16_t unit_id; unsigned char selector; sscanf(args_info.get_raw_arg, "%hu:%hhu", &unit_id, &selector); CControlValue value; value.type = CC_TYPE_RAW; // the entity is only used for the generating a control name //TODO: pass the guid through cmdline (optional) unsigned char entity[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; res = c_read_xu_control(handle, entity, unit_id, selector, &value); if(res) { print_handle_error(handle, "Unable to retrieve control value", res); goto done; } //print the raw value uint8_t * val = value.raw.data; int i=0; printf("query current value of: (LE)0x"); for(i=0; i=0; i--) { printf("%.2x", val[i]); } printf("\n"); //free the raw value alocation if(value.raw.data) free(value.raw.data); } else if(args_info.set_given) { CControlValue value; // Parse the control value if(args_info.inputs_num < 1) { res = 3; print_error("No control value specified", -1); goto done; } if(parse_control_value(args_info.inputs[0], &value)) { res = 2; print_error("Invalid control value specified", -1); goto done; } // Resolve the control Id CControlId controlId = get_control_id(handle, args_info.set_arg); if(!controlId) { res = 1; print_handle_error(handle, "Unknown control specified", -1); goto done; } // Set the new control value res = c_set_control(handle, controlId, &value); if(res) { print_handle_error(handle, "Unable to set new control value", res); goto done; } } // Set the raw control value else if(args_info.set_raw_given) { CControlValue value; // Parse the control value if(args_info.inputs_num < 1) { res = 3; print_error("No raw control value specified", -1); goto done; } uint16_t unit_id; unsigned char selector; sscanf(args_info.set_raw_arg, "%hu:%hhu", &unit_id, &selector); parse_raw_control_value (args_info.inputs[0], &value); // the entity is only used for the generating a control name //TODO: pass the guid through cmdline (optional) unsigned char entity[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; res = c_write_xu_control(handle, entity, unit_id, selector, &value); if(res) { print_handle_error(handle, "Unable to set the control value", res); goto done; } //print the raw value le and be format uint8_t * val = value.raw.data; int i=0; printf("set value of : (LE)0x"); for(i=0; i=0; i--) { printf("%.2x", val[i]); } printf("\n"); //free the raw value alocation if(value.raw.data) free(value.raw.data); } else if(args_info.save_ctrl_given) { res = save_controls( handle, args_info.save_ctrl_arg); } else if(args_info.load_ctrl_given) { res = load_controls( handle, args_info.load_ctrl_arg); } // Clean up done: if(handle) c_close_device(handle); c_cleanup(); cmdline_parser_free(&args_info); return res; } libwebcam-src-0.2.4/doxygen/0000755000175000017500000000000012234547770014741 5ustar paulopaulolibwebcam-src-0.2.4/doxygen/res/0000755000175000017500000000000012234547770015532 5ustar paulopaulolibwebcam-src-0.2.4/doxygen/res/logitech.jpg0000644000175000017500000002215212234547770020034 0ustar paulopauloÿØÿàJFIFÿíPhotoshop 3.08BIMí8BIM x8BIMó8BIM 8BIM' 8BIMõH/fflff/ff¡™š2Z5-8BIMøpÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿè8BIM8BIM8BIM@@8BIM8BIM g=4¸%`KÿØÿàJFIFHHÿîAdobed€ÿÛ„            ÿÀ4="ÿÝÿÄ?   3!1AQa"q2‘¡±B#$RÁb34r‚ÑC%’Sðáñcs5¢²ƒ&D“TdE£t6ÒUâeò³„ÃÓuãóF'”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö7GWgw‡—§·Ç×ç÷5!1AQaq"2‘¡±B#ÁRÑð3$bár‚’CScs4ñ%¢²ƒ&5ÂÒD“T£dEU6teâò³„ÃÓuãóF”¤…´•ÄÔäô¥µÅÕåõVfv†–¦¶ÆÖæö'7GWgw‡—§·ÇÿÚ ?õTĆ‚çROs¿]³ê£¦U…e†¦õ+™cÁ‚ÚÊwö¨cªÿ®¤‰HDz5ú§ÖúŸÙaéÆC3¶ -½ÃéWÓ±Ýþ ¿™{}ôéªõœî·vpËÊJkKFSÃËœcôŽØÖW^ßø%ÎfäYÔ/~cÛ²–^=#èÕS™¥ƒù, °ÂêØ]  ¬õ³/mL€go¬òíÇØÖWúkÿgùêIDF#¹hòÜĹŒò¯æñõýù¿Áz>¡ŸÓ±,ÌÊvÊ«{’NcGï=Ëè=Gë'Qê§+$zy rÐ4?Aßéw7󷪹_N>7Úz—L°tûgÒ¹±ïÛ.ö°—m{ÚÝôú¯«Õ]f>FÆ®êÞÆUkZöCd8no*H7 èêãÍcœF8ÊsÓÜŸ«‚êãú3þ»e%=˜àæøƒ!I9…ÿÐõUÇŒ¬'ÝÓ°ó«q2?H<hô÷ÿÛžŸùë±@ÎÂÇÏÄ·%»é¹»^ßõýÔA¢ ̰ãÇ(~ð!á1ú/«Ó][~›Û¹§ù_š¨õ>—Ô:k¾±ôf›:•4 ì2%Фûñ¶–¾¼IÍþ»AS3ú ¾É“K²ñF˜ù,úQù¬½›ûêÿÕlWÕfm¤Ey6z›{F©ÒÔY>M>VÞA‚=<9#[pú¡'Œnµõ‹¥ÓÒs«hÀ h·+Ó}6XF›YsYé=¬þrïæÿЮ£/êÏN˪¶XÇVÁ^úžúÉk~‹é9›Úßå­f±ú Ê}§ë_HúÉMƒÔ:c½1púIŸMöÇîÿ6ÿðV3ý ŸÎ±¾ïôŽ‘…Ò1~É„ÁU2]´~ñúO?œç9^I$”ÿÿÑôÇåìΫlúµºÍóÆÒÑ·oö”­ÍÄ¥þ·1çkœƒâ©æØ(êØ×½¯5ŠlisçÁ%›Gèüz¯¦¶ç ë{–ç>¡é¸›æ†×Xöý&}IN¦FF%P2,cw}â5A9ÔVíÕº£Œ*u›šá¸–»gµŸ¹üµG—tûC³˜÷—ÑUl{ë °ôÛ}È=.·¼VZõط´ÒMÆýd”ëQÕ0îÆnI±µµÑ!ÄH.°ÿ-åâEæÖI€ù>ÖXŒõ=ãÕ©¸Œ5Þ[Y.cËCwzv1ÛÛíÛ¾´FR)ɧ;ô·ãz¶:Òêö–½Ík{hk[ìÓéìIM÷u|a”ʽFz­Îõw~s\Öìÿ¤­}§ÐûG¨ßF'Ô‘¶?¬¨×coêÕ_Séz7{˜æë¾¿ß Týgú~›£íó³iú®éÛû‰)ÿÒõT—Ê©$§éŒÿW×>—ÚãhßèlÙý[ü'üR³ÓþÍö*¾ÉüÆßdÌóîÝ»ó÷}5òòI)ú©%òªI)ú©%òªI)ÿÙ8BIMÿâ XICC_PROFILE HLinomntrRGB XYZ Î 1acspMSFTIEC sRGBöÖÓ-HP cprtP3desc„lwtptðbkptrXYZgXYZ,bXYZ@dmndTpdmddĈvuedL†viewÔ$lumiømeas $tech0 rTRC< gTRC< bTRC< textCopyright (c) 1998 Hewlett-Packard CompanydescsRGB IEC61966-2.1sRGB IEC61966-2.1XYZ óQÌXYZ XYZ o¢8õXYZ b™·…ÚXYZ $ „¶ÏdescIEC http://www.iec.chIEC http://www.iec.chdesc.IEC 61966-2.1 Default RGB colour space - sRGB.IEC 61966-2.1 Default RGB colour space - sRGBdesc,Reference Viewing Condition in IEC61966-2.1,Reference Viewing Condition in IEC61966-2.1view¤þ_.ÏíÌ \žXYZ L VPWçmeassig CRT curv #(-27;@EJOTY^chmrw|†‹•šŸ¤©®²·¼ÁÆËÐÕÛàåëðöû %+28>ELRY`gnu|ƒ‹’š¡©±¹ÁÉÑÙáéòú &/8AKT]gqz„Ž˜¢¬¶ÁËÕàëõ !-8COZfr~Š–¢®ºÇÓàìù -;HUcq~Œš¨¶ÄÓáðþ +:IXgw†–¦µÅÕåö'7HYj{Œ¯ÀÑãõ+=Oat†™¬¿Òåø 2FZn‚–ª¾Òçû  % : O d y ¤ º Ï å û  ' = T j ˜ ® Å Ü ó " 9 Q i € ˜ ° È á ù  * C \ u Ž § À Ù ó & @ Z t Ž © Ã Þ ø.Id›¶Òî %A^z–³Ïì &Ca~›¹×õ1OmŒªÉè&Ed„£Ãã#Ccƒ¤Åå'Ij‹­Îð4Vx›½à&Il²ÖúAe‰®Ò÷@eНÕú Ek‘·Ý*QwžÅì;cвÚ*R{£ÌõGp™Ãì@j”¾é>i”¿ê  A l ˜ Ä ð!!H!u!¡!Î!û"'"U"‚"¯"Ý# #8#f#”#Â#ð$$M$|$«$Ú% %8%h%—%Ç%÷&'&W&‡&·&è''I'z'«'Ü( (?(q(¢(Ô))8)k))Ð**5*h*›*Ï++6+i++Ñ,,9,n,¢,×- -A-v-«-á..L.‚.·.î/$/Z/‘/Ç/þ050l0¤0Û11J1‚1º1ò2*2c2›2Ô3 3F33¸3ñ4+4e4ž4Ø55M5‡5Â5ý676r6®6é7$7`7œ7×88P8Œ8È99B99¼9ù:6:t:²:ï;-;k;ª;è<' >`> >à?!?a?¢?â@#@d@¦@çA)AjA¬AîB0BrBµB÷C:C}CÀDDGDŠDÎEEUEšEÞF"FgF«FðG5G{GÀHHKH‘H×IIcI©IðJ7J}JÄK KSKšKâL*LrLºMMJM“MÜN%NnN·OOIO“OÝP'PqP»QQPQ›QæR1R|RÇSS_SªSöTBTTÛU(UuUÂVV\V©V÷WDW’WàX/X}XËYYiY¸ZZVZ¦Zõ[E[•[å\5\†\Ö]']x]É^^l^½__a_³``W`ª`üaOa¢aõbIbœbðcCc—cëd@d”dée=e’eçf=f’fèg=g“géh?h–hìiCišiñjHjŸj÷kOk§kÿlWl¯mm`m¹nnknÄooxoÑp+p†pàq:q•qðrKr¦ss]s¸ttptÌu(u…uáv>v›vøwVw³xxnxÌy*y‰yçzFz¥{{c{Â|!||á}A}¡~~b~Â#„å€G€¨ kÍ‚0‚’‚ôƒWƒº„„€„ã…G…«††r†×‡;‡ŸˆˆiˆÎ‰3‰™‰þŠdŠÊ‹0‹–‹üŒcŒÊ1˜ÿŽfŽÎ6žnÖ‘?‘¨’’z’ã“M“¶” ”Š”ô•_•É–4–Ÿ— —u—à˜L˜¸™$™™üšhšÕ›B›¯œœ‰œ÷dÒž@ž®ŸŸ‹Ÿú i Ø¡G¡¶¢&¢–££v£æ¤V¤Ç¥8¥©¦¦‹¦ý§n§à¨R¨Ä©7©©ªª««u«é¬\¬Ð­D­¸®-®¡¯¯‹°°u°ê±`±Ö²K²Â³8³®´%´œµµŠ¶¶y¶ð·h·à¸Y¸Ñ¹J¹Âº;ºµ».»§¼!¼›½½¾ ¾„¾ÿ¿z¿õÀpÀìÁgÁãÂ_ÂÛÃXÃÔÄQÄÎÅKÅÈÆFÆÃÇAÇ¿È=ȼÉ:ɹÊ8Ê·Ë6˶Ì5̵Í5͵Î6ζÏ7ϸÐ9кÑ<ѾÒ?ÒÁÓDÓÆÔIÔËÕNÕÑÖUÖØ×\×àØdØèÙlÙñÚvÚûÛ€ÜÜŠÝÝ–ÞÞ¢ß)߯à6à½áDáÌâSâÛãcãëäsäü儿 æ–çç©è2è¼éFéÐê[êåëpëûì†ííœî(î´ï@ïÌðXðåñrñÿòŒóó§ô4ôÂõPõÞömöû÷Šøø¨ù8ùÇúWúçûwüü˜ý)ýºþKþÜÿmÿÿÿîAdobed@ÿÛ„ÿÀ4=ÿÝÿÄ¢     u!"1A2# QBa$3Rqb‘%C¡±ð&4r ÁÑ5'áS6‚ñ’¢DTsEF7Gc(UVW²ÂÒâòdƒt“„e£³ÃÓã)8fóu*9:HIJXYZghijvwxyz…†‡ˆ‰Š”•–—˜™š¤¥¦§¨©ª´µ¶·¸¹ºÄÅÆÇÈÉÊÔÕÖרÙÚäåæçèéêôõö÷øùúm!1"AQ2aqB#‘R¡b3 ±$ÁÑCrðá‚4%’ScDñ¢²&5T6Ed' sƒ“FtÂÒâòUeuV7„…£³ÃÓãó)”¤´ÄÔäô•¥µÅÕåõ(GWf8v†–¦¶ÆÖæögw‡—§·Ç×ç÷HXhxˆ˜¨¸ÈØèø9IYiy‰™©¹ÉÙéù*:JZjzŠšªºÊÚêúÿÚ ?ßãߺ÷Q*ꩨiª««ª`£¢¢§žª®®®h©éiiiãiª*jj&d†x"BÎìÁUA$Øq¼âƒ=hÐIq'ý\:¡¿”?Í›9·©·OWwøÓñZºLÎ?o|­“®è»?¶>Mnl­O˜Ú:k:’QM³p¬odnŠ&ÛÏXñCާ©ˆýø7±Ú¥¹"Be¸ÁÐ ƒç#ŽòPu×I°×:û©´ì6GpºÞ×låê•[¶Å–æE%Z;+sRÁî¦C%B¬ŠÆE)?Ê'züÄùó[²»êŸ¿þVçþã09 —¶º»äŸamÞÁÌîÝÃU2GÞ™X6þÙÛ›CgUâæŠJ¨é°4GU%ÜUGî×ßvØì$´Œ•[°½Êš´P“Jê$ÔþÖ‚´¡É²|é¹{?1oö—·’ò„s¡{¦C+È5…$q•«•B5Éá¬á?[÷÷|u·Æ~¦ÝýÓÛ9¯à{/gQGQ[,0IY‘Éd+jbÇá°L|*Óäó™ì­LT´”è5I4«{.¦-Ós·Úl¥½¸©Wâv¡¢Š+ƒVbvTVa—ÞÚûqÍ^ìó®ÇÈ\—aõõü…T#DRòÍ+š†Õ¤‘É¢ªž&€ÓÀßÿÌ{äçÊiûo³éªzïâýv+1K骽¯‚ÇD”Y-ml’ÏSM.ù¢Ëáa:ëê«êa5“ŸKœ9fãš·]Éw×)¶ä*#eÒê#‰H£.¢’¬ô%•h%`å1~ò<»÷Jö·Û+?l=·x÷ÿy⼈ÝnÑ\M"Bb¨ºGeae"ÊF˜`·GðTk–c Òv÷$õÏþ½ïÝ{¯ÿÐßãߺ÷Táüë»ÓluçÆ­ƒÑ;u×쪘ÝÙ²ºxnœ^SøFKntšÉ>ùïÌ¥%Q–$l§XmzÌÂdC<ÙèÒáK·mîo#Š8ËÈ0P $¨$ KM~Uê;÷?~³Ø¹]Úþùmlî&Ž)fgXÄp³µ6*c ƒÅÝF$jÜݸ¾Jo\ÿtç±Qm½… ÄuïMu­¬;s§ºwnÓUSõçZm¼t:*J\.>é¡DZªçšv·sfͶÁµZíªçÃ23,šۆHS†zâǾîoãseÅå´f_·-­ãT·Šôðª‚EDq³9\¨6Géo–})ü¿:_¥z·§ßýùÙØÜ2á6Ó— IUQ™©Ù“vã­ÎÕä²4›{µö\nÞO%=:’޲Š?¹zºÚZi!]Úñ· Âöð×õ$44Q…P|è´óë´ÞÒr|‡í¯%ò¬*†K]¾/‘B‰.—Ò¤ÖYÚI I=Ù' +µŸ=_[ušv—ÉÿƒÝ‡ÅýæÙY6eaªpÂMô›~ –n–à‚%•BªXi¤*š.Lð£ `hÀ0¨È9ÅAáéÔ™ousi!šÒæH¥*WR1SFeª‘PA ŠÐƒB:ØGao뛽6ÆâÚ;odoM±¶÷fÝ®Êe1x[…ÝXªlΦq‘©‚D𶆩CW¸úotÇBÎ+1ˆÎQ¦C”Çf1ò–Xë±UÔÙ9 Rª’Y fRy®=û¯tåïÝ{¯ÿÑßãߺ÷ZÜ”zS5½~;|mî¼rÍQ‡èo0G½iãÚ-¯Úûz«hE¸jd^#‹»©q4|ð‰‡³¾Y‘bæ ´¾cf*Û?`¡üúǽFÝwyíùqh ¼cŸ& çR_BêÃì$³`ü2¿ãŽkkãýYüæs8<ƒ$b6Ü4ðœbyVLt•eÍ;°»ˆ%6»[زë™[÷¾¶[P£èÓùˆTÓPòëö/»Ò^ûw¸mˆÂMöt1ÊÁ@7J5ÇV Åc|ÂH ë*Ô$°ü—øÅÞ$~6e™ÏÂ5Vìùi×]‘øEòŸãu^\†|ÑaðGaî>ÙéŒngº6—rQlÅP§TÙb˜¨Á9ë¤>ÍsÔ^á{y°ï¥<=Î8„QQ¢º…BL­,ÉSIëTuÖW£u±zßæó3øÅÖ_;ïgmš´›/jÑoîònªì.”ìÞÒÍá[ìhð»o¦{nà+66áÂí¨š5¸f’¿IUS0ÃE-BCYHìêR=_?kÿ,ÏŽÝÏ´öŽtSo-»˜Úû' °=Öý‹Ø]i[œÚ8*V¦Äí}ÌvçÛQn|" ¤Ž–ô¨ðG#ªiV`}׺>%üDé…`:ƒ¡ö¶?fìc™Èî9°¸È¤Hª·cÂsü•]\õ™,¾s,ÔñšŠº©åž] seߺ÷Fߺ÷_ÿÒßãߺ÷A_vtß_|„ê­óÒý«‚‡rìÃÁÏÜx‰ež˜ÍLòEUISKYK$5T9,^BšªZˆ%§©†9†QîÈï‹,fޤöõyƒö‹·}§oßvËýŸv¶í×1´r!$UXPЂH⬤2š €z¡=µŠïŸåÛ\:g´ºÓ;ß]/G<˜Þšîí£õ†›¿ƒmÎÐÛ¸Ì]d´õ¸ªEð6Bš1M*Æ–’1J¥–ú¯?×%¾ãJºÈ@WÏs#µ£PÅjZ„C‡—V¼åìlöû%Ï']oü€\ÇgyeÉqjšk½í¬1»øhªÈ.b]XPîB?åuÖ­Ÿ¹>NnÉ©–—k÷?`Á¿‚¬2­R®V¾ÑÎ šš¹ªȈ^8‘R5g ‘o×v÷RÙ$9h XØàÔ©!xz-xŸ>¥»ï*o·¶óÅþåAk»ïRÞà  ‚eC!!Æ¡ª]T\ª€IP­âƒ ‰Æþ¥£2ƒ¬ÁÄípoë_XúþÈzÈ>µù=“üÕ¾1Þ³Ø=KUòÏùr|‚Üòl*nͤÇÒÂø÷ÌK_W³÷ü††¯„b2ÈÉVD*0yŒ_޳ʼnÉSL2žëÝl4 nÍÁúþn=û¯uß¿uî¿ÿÓÞS5Û'Þ{¦?ïžÂÞ{ÛûÄ2"1Žþèä¶þ?øiÆ7û“]üw_—Ξ?´6®=׺wÝÍÔÛ#4›wwö>ÌÛyƆš¥±YÁ ­¦¥­—ÃGW] EB5-\Þ˜¥ŸÇÂ’}û¯uÞýì>¨Úqãè»vlì:f£–|mãÈã#|…â²–’©Ù壧(’p¾(õ L.=û¯tÍÞ'mÖ>Omåz®¯¨iú¯sö¹ÌñÆÃ[‘Ànjm»âÃà)aj,†Ü’ªG¥—#÷*±d kqÙìÎ6– 9¸(¾ökd*‰"—pøÑÇÛ@ewñ±P@¿¿uî—U]«Ô³lÈ7åfüÙ3ljš¿²¥Ü³g1Rá*2B¡é†ÓÕ´Í ÙE«…ãûe¼âT+£P {¯t d>Zõ½jmm­íØòõÞàëíß¹_}.á‰ÖŸtmmË€Ã>ÖHb×ÜŠ<¬³Ï•¨ˆD„Ÿ~ëÝô‘×ÿÜŸô“ýõÚßèûì‰ÿ}Žãºÿaæûoºþ7÷Ãü?uûWòô~®=û¯uÿÔÜOº7 { åŸLoüÞxÖm*í\ v_klÙ¼££Ëåóû.|m\;W˜¨‚J¸±ò”ÖŠ¶RIߺ÷@öØÞÛCkÐ|«¦ì=™¾rÙnýÝ[‡vly:Çyä+{KaîM¥ÀìÍ«AØ-coKM-ø¼£š€¸™‘bs'¿uî²t6+wüpÝT.úÛ;Ë;]¹z¥v&ÕÝcmnNÈ\nËÆdãÝ]g’lc3ج…NZ¶˜æxÅqB|Å£·¿uîƒÿŒ{9œ‹gUbp9F ÈüZù3£œãª)¨`Íe~DåäÇíúЦŒPÐåž&¿Ú´‹**“§J“ïÝ{¨UÝòì_‡ùêH{ofâúee6hVaú‡!›Ý¾s[_ˆ¥ÌRí-ݵ2pî\Ubjèër8šZù1éTŒ®«3‘î½ÒŸ³iö_cu·~ÈÝ»Ù]MgöŽäßÛ—«*°-¹Ø;ŸgíÝ·„íGNU Lesser General Public License (LGPL). \section sec_introduction Latest version Note that the latest version of the Webcam Library and this API documentation can always be found on the Webcam-tools website. \section sec_feedback Questions and feedback There is a forum for developers and users of the Webcam Library. Please feel free to post your questions and comments: Webcam-tools discussion forums */ libwebcam-src-0.2.4/doxygen/html/0000755000175000017500000000000012234547770015705 5ustar paulopaulolibwebcam-src-0.2.4/doxygen/html/libwebcam/0000755000175000017500000000000012234547770017632 5ustar paulopaulolibwebcam-src-0.2.4/doxygen/html/libwebcam/footer.html0000644000175000017500000000040312234547770022013 0ustar paulopaulo
Generated on $datetime for $projectname by Doxygen $doxygenversion
Copyright © 2006-2008 Logitech.
libwebcam-src-0.2.4/doxygen/html/libwebcam/default.css0000644000175000017500000001731512234547770021777 0ustar paulopauloBODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV { font-family: "Segoe UI", "Bitstream Vera Sans", Tahoma, sans-serif; } BODY,TD { font-size: 90%; } H1 { text-align: center; font-size: 160%; } H2 { font-size: 120%; } H3 { font-size: 100%; } *.logiheader { font-family: "Segoe UI", "Bitstream Vera Sans", Tahoma, sans-serif; font-size: 150%; color: #777777; } CAPTION { font-weight: bold } DIV.qindex { width: 100%; background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; line-height: 140%; } DIV.nav { width: 100%; background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; padding: 2px; line-height: 140%; } DIV.navtab { background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } TD.navtab { font-size: 70%; } A.qindex { text-decoration: none; font-weight: bold; color: #1A419D; } A.qindex:visited { text-decoration: none; font-weight: bold; color: #1A419D } A.qindex:hover { text-decoration: none; background-color: #ddddff; } A.qindexHL { text-decoration: none; font-weight: bold; background-color: #6666cc; color: #ffffff; border: 1px double #9295C2; } A.qindexHL:hover { text-decoration: none; background-color: #6666cc; color: #ffffff; } A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff } A.el { text-decoration: none; font-weight: bold } A.elRef { font-weight: bold } A.code:link { text-decoration: none; font-weight: normal; color: #0000FF} A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF} A.codeRef:link { font-weight: normal; color: #0000FF} A.codeRef:visited { font-weight: normal; color: #0000FF} A:hover { text-decoration: none; background-color: #f2f2ff } DL.el { margin-left: -1cm } .fragment { font-family: monospace, fixed; font-size: 95%; } PRE.fragment { border: 1px solid #CCCCCC; background-color: #f5f5f5; margin-top: 4px; margin-bottom: 4px; margin-left: 2px; margin-right: 8px; padding-left: 6px; padding-right: 6px; padding-top: 4px; padding-bottom: 4px; } DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px } DIV.groupHeader { margin-left: 16px; margin-top: 12px; margin-bottom: 6px; font-weight: bold; } DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% } BODY { background: white; color: black; margin-right: 20px; margin-left: 20px; } TD.indexkey { background-color: #e8eef2; font-weight: bold; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px; border: 1px solid #CCCCCC; } TD.indexvalue { background-color: #e8eef2; font-style: italic; padding-right : 10px; padding-top : 2px; padding-left : 10px; padding-bottom : 2px; margin-left : 0px; margin-right : 0px; margin-top : 2px; margin-bottom : 2px; border: 1px solid #CCCCCC; } TR.memlist { background-color: #f0f0f0; } P.formulaDsp { text-align: center; } IMG.formulaDsp { } IMG.formulaInl { vertical-align: middle; } SPAN.keyword { color: #008000 } SPAN.keywordtype { color: #604020 } SPAN.keywordflow { color: #e08000 } SPAN.comment { color: #800000 } SPAN.preprocessor { color: #806020 } SPAN.stringliteral { color: #002080 } SPAN.charliteral { color: #008080 } .mdescLeft { padding: 0px 8px 4px 8px; font-size: 80%; font-style: italic; background-color: #FAFAFA; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; } .mdescRight { padding: 0px 8px 4px 8px; font-size: 80%; font-style: italic; background-color: #FAFAFA; border-top: 1px none #E0E0E0; border-right: 1px none #E0E0E0; border-bottom: 1px none #E0E0E0; border-left: 1px none #E0E0E0; margin: 0px; } .memItemLeft { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memItemRight { padding: 1px 8px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplItemLeft { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplItemRight { padding: 1px 8px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: none; border-right-style: none; border-bottom-style: none; border-left-style: none; background-color: #FAFAFA; font-size: 80%; } .memTemplParams { padding: 1px 0px 0px 8px; margin: 4px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-color: #E0E0E0; border-right-color: #E0E0E0; border-bottom-color: #E0E0E0; border-left-color: #E0E0E0; border-top-style: solid; border-right-style: none; border-bottom-style: none; border-left-style: none; color: #606060; background-color: #FAFAFA; font-size: 80%; } .search { color: #003399; font-weight: bold; } FORM.search { margin-bottom: 0px; margin-top: 0px; } INPUT.search { font-size: 75%; color: #000080; font-weight: normal; background-color: #e8eef2; } TD.tiny { font-size: 75%; } a { color: #1A41A8; } a:visited { color: #2A3798; } .dirtab { padding: 4px; border-collapse: collapse; border: 1px solid #84b0c7; } TH.dirtab { background: #e8eef2; font-weight: bold; } HR { height: 1px; border: none; border-top: 1px solid black; } /* Style for detailed member documentation */ .memtemplate { font-size: 80%; color: #606060; font-weight: normal; } .memnav { background-color: #e8eef2; border: 1px solid #84b0c7; text-align: center; margin: 2px; margin-right: 15px; padding: 2px; } .memitem { padding: 4px; background-color: #eef3f5; border-width: 1px; border-style: solid; border-color: #dedeee; -moz-border-radius: 8px 8px 8px 8px; } .memname { white-space: nowrap; font-weight: bold; } .memdoc{ padding-left: 10px; } .memproto { background-color: #d5e1e8; width: 100%; border-width: 1px; border-style: solid; border-color: #84b0c7; font-weight: bold; -moz-border-radius: 8px 8px 8px 8px; } .paramkey { text-align: right; } .paramtype { white-space: nowrap; } .paramname { color: #602020; font-style: italic; } /* End Styling for detailed member documentation */ /* for the tree view */ .ftvtree { font-family: sans-serif; margin:0.5em; } .directory { font-size: 9pt; font-weight: bold; } .directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; } .directory > h3 { margin-top: 0; } .directory p { margin: 0px; white-space: nowrap; } .directory div { display: none; margin: 0px; } .directory img { vertical-align: -30%; } libwebcam-src-0.2.4/doxygen/html/libwebcam/header.html0000644000175000017500000000105112234547770021745 0ustar paulopaulo $title
Webcam Library Reference Documentation  Logitech logo
libwebcam-src-0.2.4/doxygen/libwebcam.cfg0000644000175000017500000015725212234547770017363 0ustar paulopaulo# Doxyfile 1.5.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = "Webcam Library" # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = $(DOCDIR)/libwebcam # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Farsi, Finnish, French, German, Greek, # Hungarian, Italian, Japanese, Japanese-en (Japanese with English messages), # Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # and Ukrainian. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = YES # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = YES # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = $(SRCDIR) # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = $(SRCDIR) # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the DETAILS_AT_TOP tag is set to YES then Doxygen # will output the detailed description near the top, like JavaDoc. # If set to NO, the detailed description appears after the member # documentation. DETAILS_AT_TOP = YES # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = $(SRCDIR)/libwebcam \ $(SRCDIR)/common/include \ $(SRCDIR)/doxygen/doc/libwebcam/main.txt # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = $(SRCDIR)/libwebcam/compat.h # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = $(SRCDIR) # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES (the default) # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES (the default) # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentstion. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = $(GENERATE_HTML) # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = $(SRCDIR)/doxygen/html/libwebcam/header.html # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = $(SRCDIR)/doxygen/html/libwebcam/footer.html # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = $(SRCDIR)/doxygen/html/libwebcam/default.css # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = $(GENERATE_CHM) # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = ../$(PROJECT).chm # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = $(HHC_PATH) # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = $(GENERATE_CHI) # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # If the GENERATE_TREEVIEW tag is set to YES, a side panel will be # generated containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, # Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are # probably better off using the HTML help feature. GENERATE_TREEVIEW = YES # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = $(GENERATE_LATEX) # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = $(PAPER_SIZE) # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = NO # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = NO # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = YES # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = $(GENERATE_RTF) # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = $(GENERATE_MAN) # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .1 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = $(GENERATE_XML) # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = $(DOCDIR)/$(PROJECT).tag # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = $(PERL_PATH) #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = $(HAVE_DOT) # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = $(DOT_PATH) # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is enabled by default, which results in a transparent # background. Warning: Depending on the platform used, enabling this option # may lead to badly anti-aliased labels on the edges of a graph (i.e. they # become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- # The SEARCHENGINE tag specifies whether or not a search engine should be # used. If set to NO the values of all tags below this one will be ignored. SEARCHENGINE = NO libwebcam-src-0.2.4/libwebcam/0000755000175000017500000000000012234547770015211 5ustar paulopaulolibwebcam-src-0.2.4/libwebcam/COPYING0000644000175000017500000010451312234547770016250 0ustar paulopaulo GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. 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 . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . libwebcam-src-0.2.4/libwebcam/COPYING.LESSER0000644000175000017500000001672712234547770017255 0ustar paulopaulo GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, "this License" refers to version 3 of the GNU Lesser General Public License, and the "GNU GPL" refers to version 3 of the GNU General Public License. "The Library" refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An "Application" is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A "Combined Work" is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the "Linked Version". The "Minimal Corresponding Source" for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The "Corresponding Application Code" for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. libwebcam-src-0.2.4/libwebcam/dynctrl/0000755000175000017500000000000012234547770016670 5ustar paulopaulolibwebcam-src-0.2.4/libwebcam/dynctrl/uvcconfig.xsd0000644000175000017500000001661012234547770021377 0ustar paulopaulo libwebcam-src-0.2.4/libwebcam/CMakeLists.txt0000644000175000017500000000607112234547770017755 0ustar paulopaulo# # GENERAL # # Require CMake 2.6 because of the Debian packaging. cmake_minimum_required (VERSION 2.6) project (LIBWEBCAM) # # TARGETS # add_library (webcam SHARED libwebcam.c dynctrl.c) add_library (webcam_static STATIC libwebcam.c dynctrl.c) set_target_properties (webcam PROPERTIES VERSION 0.2.4 SOVERSION 0 CLEAN_DIRECT_OUTPUT 1 OUTPUT_NAME "webcam") set_target_properties (webcam_static PROPERTIES VERSION 0.2.4 SOVERSION 0 CLEAN_DIRECT_OUTPUT 1 OUTPUT_NAME "webcam") # # COMPILATION AND LINKING # # Require LibXML #include (FindLibXml2) include (FindPkgConfig) pkg_check_modules (LIBXML2 REQUIRED libxml-2.0) # Check V4L2 try_compile (HAS_V4L2_STRING_CONTROLS ${CMAKE_BINARY_DIR}/ ${CMAKE_CURRENT_SOURCE_DIR}/../common/build/cmake_try_v4l2_ctrl_type_string.c) if (HAS_V4L2_STRING_CONTROLS) message("** Your V4L2 has V4L2_CTRL_TYPE_STRING support. Enabling raw control support.") add_definitions (-DENABLE_RAW_CONTROLS) else (HAS_V4L2_STRING_CONTROLS) message("** Your V4L2 does not have V4L2_CTRL_TYPE_STRING support. Compiling without raw control support.") endif (HAS_V4L2_STRING_CONTROLS) # Includes include_directories (include ${LIBXML2_INCLUDE_DIRS} ../common/include) # Libraries target_link_libraries (webcam ${LIBXML2_LIBRARIES}) target_link_libraries (webcam_static ${LIBXML2_LIBRARIES}) # Compiler flags set_target_properties (webcam PROPERTIES COMPILE_FLAGS "-Wall" ) set_target_properties (webcam_static PROPERTIES COMPILE_FLAGS "-Wall ${EXTRA_COMPILE_FLAGS}" ) # create libwebcam.pc (for pkg-config) execute_process ( COMMAND sh -c "sed -e 's_<--PREFIX--!>_${CMAKE_INSTALL_PREFIX}_g' ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/libwebcam.pc_base > ${CMAKE_CURRENT_BINARY_DIR}/libwebcam.pc" RESULT_VARIABLE PC_EXECUTE_RESULT ERROR_QUIET ) if (PC_EXECUTE_RESULT) message(ERROR " Unable to parse ${CMAKE_CURRENT_SOURCE_DIR}/pkgconfig/libwebcam.pc_base") else (PC_EXECUTE_RESULT) message("** created libwebcam.pc") endif (PC_EXECUTE_RESULT) # # INSTALLATION # if (NOT DEFINED CMAKE_INSTALL_LIBDIR) if (DEFINED LIB_INSTALL_DIR) SET(CMAKE_INSTALL_LIBDIR ${LIB_INSTALL_DIR}) else (DEFINED LIB_INSTALL_DIR) SET(CMAKE_INSTALL_LIBDIR "lib") endif (DEFINED LIB_INSTALL_DIR) endif (NOT DEFINED CMAKE_INSTALL_LIBDIR) if (${CMAKE_INSTALL_LIBDIR} MATCHES "^/") message("** Installation directory for libwebcam: ${CMAKE_INSTALL_LIBDIR}") else (${CMAKE_INSTALL_LIBDIR} MATCHES "^/") message("** Installation directory for libwebcam: ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}") endif (${CMAKE_INSTALL_LIBDIR} MATCHES "^/") install ( TARGETS webcam webcam_static LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT LIBWEBCAM ) # Default permissions for DIRECTORY files: rw-r--r-- # Default permissions for PROGRAMS files: rwxr-xr-x # Note that having absolute paths here requires CPACK_SET_DESTDIR to be set to "ON". install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/libwebcam.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig ) install ( FILES ../common/include/webcam.h DESTINATION ${CMAKE_INSTALL_PREFIX}/include ) libwebcam-src-0.2.4/libwebcam/pkgconfig/0000755000175000017500000000000012234547770017160 5ustar paulopaulolibwebcam-src-0.2.4/libwebcam/pkgconfig/libwebcam.pc_base0000644000175000017500000000033512234547770022424 0ustar paulopauloprefix=<--PREFIX--!> exec_prefix=${prefix} libdir=${exec_prefix}/lib includedir=${exec_prefix}/include Name: libwebcam Description: The Webcam Library Version: 0.2.3 Libs: -L${libdir} -lwebcam Cflags: -I${includedir} libwebcam-src-0.2.4/libwebcam/test.c0000644000175000017500000002474112234547770016344 0ustar paulopaulo/* * Test program for libwebcam. * * * Copyright (c) 2006-2007 Logitech. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 . */ #include #include #include #include #include #include void print_device_info (CHandle handle, char *device_name) { assert(handle || device_name); unsigned int size = sizeof(CDevice) + (device_name ? strlen(device_name) : 32) + 84; CDevice *info = (CDevice *)malloc(size); assert(info); if(handle) printf(" Getting device information for handle %d ...\n", handle); else if(device_name) printf(" Getting device information for device name '%s' ...\n", device_name); int ret = c_get_device_info(handle, device_name, info, &size); if(ret) { fprintf(stderr, " Failed to c_get_device_info (%d).\n", ret); } else { printf(" { shortName = '%s', name = '%s', driver = '%s', location = '%s', vid = %04x, pid = %04x, bcd = %d }\n", info->shortName, info->name, info->driver, info->location, info->usb.vendor, info->usb.product, info->usb.release); } free(info); } void print_control_info(CControl *control) { printf(" { id = %d, name = '%s', type = %d, flags = %d", control->id, control->name, control->type, control->flags); if(control->type == CC_TYPE_CHOICE) { printf(", choice = {"); for(int index = 0; index < control->choices.count; index++) { printf(" '%s'[%d]", control->choices.list[index].name, control->choices.list[index].index); } printf(" }"); } else { printf(", min = %d, max = %d, def = %d, step = %d", control->min.value, control->max.value, control->def.value, control->step.value); } printf(" }\n"); } void print_device_controls(CHandle handle) { unsigned int size = 0, count = 0; printf(" Getting control information for handle %d ...\n", handle); CResult ret = c_enum_controls(handle, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { CControl *controls = (CControl *)malloc(size); ret = c_enum_controls(handle, controls, &size, &count); if(ret) fprintf(stderr, "Unable to c_enum_controls (%d).\n", ret); /* printf(" Buffer size = %d (%d controls of %d bytes)\n", size, count, sizeof(CControl));*/ for(int i = 0; i < count; i++) { CControl *control = &controls[i]; printf(" Control found: %s\n", control->name); print_control_info(control); } free(controls); } else { printf(" No controls found (ret = %d).\n", ret); } } void print_frame_intervals(CHandle handle, CPixelFormat *pixelformat, CFrameSize *framesize) { unsigned int size = 0, count = 0; CResult ret = c_enum_frame_intervals(handle, pixelformat, framesize, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { CFrameInterval *intervals = (CFrameInterval *)malloc(size); ret = c_enum_frame_intervals(handle, pixelformat, framesize, intervals, &size, &count); if(ret) fprintf(stderr, "Unable to c_enum_frame_intervals (%d).\n", ret); /* printf(" Buffer size = %d (%d frame intervals of %d bytes)\n", size, count, sizeof(CFrameInterval));*/ for(int i = 0; i < count; i++) { CFrameInterval *frameinterval = &intervals[i]; if(framesize->type == CF_INTERVAL_DISCRETE) { printf(" { discrete: %u/%u }\n", frameinterval->n, frameinterval->d); } else if(framesize->type == CF_INTERVAL_CONTINUOUS) { printf(" { continuous: min { %u/%u } .. max { %u/%u } }\n", frameinterval->min_n, frameinterval->min_d, frameinterval->max_n, frameinterval->max_d); } else if(framesize->type == CF_INTERVAL_STEPWISE) { printf(" { stepwise: min { %u/%u } .. max { %u/%u } / " "stepsize { %u/%u } }\n", frameinterval->min_n, frameinterval->min_d, frameinterval->max_n, frameinterval->max_d, frameinterval->step_n, frameinterval->step_d); } } free(intervals); } else { printf(" No frame intervals found (ret = %d).\n", ret); } } void print_frame_sizes(CHandle handle, CPixelFormat *pixelformat) { unsigned int size = 0, count = 0; CResult ret = c_enum_frame_sizes(handle, pixelformat, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { CFrameSize *sizes = (CFrameSize *)malloc(size); ret = c_enum_frame_sizes(handle, pixelformat, sizes, &size, &count); if(ret) fprintf(stderr, "Unable to c_enum_frame_sizes (%d).\n", ret); /* printf(" Buffer size = %d (%d frame sizes of %d bytes)\n", size, count, sizeof(CFrameSize));*/ for(int i = 0; i < count; i++) { CFrameSize *framesize = &sizes[i]; if(framesize->type == CF_SIZE_DISCRETE) { printf(" { discrete: width = %u, height = %u }\n", framesize->width, framesize->height); print_frame_intervals(handle, pixelformat, framesize); } else if(framesize->type == CF_SIZE_CONTINUOUS) { printf(" { continuous: min { width = %u, height = %u } .. " "max { width = %u, height = %u } }\n", framesize->min_width, framesize->min_height, framesize->max_width, framesize->max_height); printf(" Refusing to enumerate frame intervals.\n"); break; } else if(framesize->type == CF_SIZE_STEPWISE) { printf(" { stepwise: min { width = %u, height = %u } .. " "max { width = %u, height = %u } / " "stepsize { width = %u, height = %u } }\n", framesize->min_width, framesize->min_height, framesize->max_width, framesize->max_height, framesize->step_width, framesize->step_height); printf(" Refusing to enumerate frame intervals.\n"); break; } } free(sizes); } else { printf(" No frame sizes found (ret = %d).\n", ret); } } void print_frame_formats(CHandle handle) { unsigned int size = 0, count = 0; printf(" Getting frame format information for handle %d ...\n", handle); CResult ret = c_enum_pixel_formats(handle, NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { CPixelFormat *formats = (CPixelFormat *)malloc(size); ret = c_enum_pixel_formats(handle, formats, &size, &count); if(ret) fprintf(stderr, "Unable to c_enum_frame_formats (%d).\n", ret); /* printf(" Buffer size = %d (%d formats of %d bytes)\n", size, count, sizeof(CPixelFormat));*/ for(int i = 0; i < count; i++) { CPixelFormat *format = &formats[i]; printf(" { fourcc = '%s', name = '%s', mimeType = '%s' }\n", format->fourcc, format->name, (format->mimeType ? format->mimeType : "")); print_frame_sizes(handle, format); } free(formats); } else { printf(" No frame formats found (ret = %d).\n", ret); } } void print_error_text(CResult error) { char *text = c_get_error_text(error); if(text) { printf("Error text for error %d: '%s'\n", error, text); free(text); } else { printf("ERROR: Unable to get the text for error %d\n", error); } } void get_brightness(CHandle handle) { CControlValue value; CResult ret = c_get_control(handle, CC_BRIGHTNESS, &value); if(ret) { printf("Failed to get brightness. (ret = %d)\n", ret); } else { printf("Current brightness = %d\n", value.value); } } void set_brightness(CHandle handle, int val) { CControlValue value; value.value = val; CResult ret = c_set_control(handle, CC_BRIGHTNESS, &value); if(ret) { printf("Failed to set brightness. (ret = %d)\n", ret); } else { printf("Successfully set brightness to = %d\n", value.value); } } void enum_devices() { CResult ret; unsigned int size = 0, count = 0; printf("Enumerating devices ...\n"); ret = c_enum_devices(NULL, &size, &count); if(ret == C_BUFFER_TOO_SMALL) { CDevice *devices = (CDevice *)malloc(size); ret = c_enum_devices(devices, &size, &count); if(ret) fprintf(stderr, "Unable to c_enum_devices (%d).\n", ret); /* printf(" Buffer size = %d (%d devices of %d bytes)\n\n", size, count, sizeof(CDevice));*/ for(int i = 0; i < count; i++) { CDevice *device = &devices[i]; printf(" Device found: %s\n", device->shortName); CHandle handle = c_open_device(device->shortName); if(handle == 0) { printf(" Failed to open device '%s'.\n", device->shortName); continue; } printf(" Opened device '%s' successfully (handle = %d)\n", device->shortName, handle); print_device_info(handle, NULL); print_device_controls(handle); /* print_frame_formats(handle);*/ c_close_device(handle); printf(" Closed device '%s' (handle = %d)\n\n", device->shortName, handle); handle = 0; } free(devices); printf("Done.\n"); } else { printf("No devices found.\n"); } } void add_control_mappings() { CResult ret; CDynctrlInfo info; memset(&info, 0, sizeof(info)); printf("Adding control mappings ...\n"); ret = c_add_control_mappings_from_file("dynctrl/logitech.xml", &info); if(ret) { printf("An error occurred trying to add the control mappings in dynctrl/logitech.xml:\n"); print_error_text(ret); } else { printf(" Control mappings successfully added (%d controls, %d messages).\n", info.stats.controls.successful + info.stats.controls.failed, info.message_count); if(info.message_count) { for(int i = 0; i < info.message_count; i++) { CDynctrlMessage *msg = &info.messages[i]; printf(" Message %d: { line = %d, col = %d, text = '%s' }\n", i, msg->line, msg->col, msg->text); } } } if(info.messages) free(info.messages); } int main () { CResult ret; printf("\nTesting libwebcam ...\n"); // Initialize the library ret = c_init(); if(ret) fprintf(stderr, "Unable to c_init (%d).\n", ret); // Get device information print_device_info(0, "video0"); print_device_info(0, "video1"); print_device_info(0, "video2"); // Enumerate the devices enum_devices(); CHandle hDevice = c_open_device("video0"); get_brightness(hDevice); sleep(2); set_brightness(hDevice, 0); sleep(2); set_brightness(hDevice, 255); sleep(2); set_brightness(hDevice, 127); c_close_device(hDevice); // Enumerate the devices //enum_devices(); // Test error codes print_error_text(C_SUCCESS); print_error_text(C_SYNC_ERROR); print_error_text(123); // Test adding of control mappings add_control_mappings(); // Release the library c_cleanup(); printf("Exiting.\n"); return 0; } libwebcam-src-0.2.4/libwebcam/libwebcam.c0000755000175000017500000026414612234547770017322 0ustar paulopaulo/** * \file * Webcam library implementation. * * \ingroup libwebcam */ /* * Copyright (c) 2006-2010 Logitech. * * This file is part of libwebcam. * * libwebcam is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libwebcam 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libwebcam. If not, see . */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "webcam.h" #include "libwebcam.h" #include "compat.h" #ifdef USE_LOGITECH_DYNCTRL #include #endif /// A flag indicating whether the library was initialized. int initialized = 0; /// A list of webcam devices found in the system. static DeviceList device_list; /// The fixed size list of file handles. HandleList handle_list; /* * Forward declarations */ void print_libwebcam_error (char *format, ...); static void print_libwebcam_c_error (CResult error, char *format, ...); static unsigned int get_control_dynamics_length(Device *device, unsigned int *names_length, unsigned int *choices_length); static Control *find_control_by_id (Device *dev, CControlId id); static CResult refresh_device_list (void); static Device *find_device_by_name (const char *name); static int get_device_dynamics_length (CDevice *device); static int get_devices_dynamics_length (void); int open_v4l2_device(char *device_name); static CResult read_v4l2_control(Device *device, Control *control, CControlValue *value, CHandle hDevice); static CResult write_v4l2_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice); static CControlId get_control_id_from_v4l2 (int v4l2_id, Device *dev); static CResult get_device_usb_info (Device *device, CUSBInfo *usbinfo); static CResult get_mimetype_from_fourcc(char **mimetype, unsigned int fourcc); static CHandle create_handle(Device *device); static void close_handle(CHandle handle); /* * Devices */ /** * Opens a camera device. * * The function returns a handle that can be used for all functions that require * a device handle. * * @param device_name Name of the device to open. * Two different naming schemes are accepted: Full device names * (e.g. '/dev/video0') and short names (e.g. 'video0') as * returned by c_enum_devices(). * @return * - a device handle greater than zero on success * - 0 if an error has occurred */ CHandle c_open_device (const char *device_name) { CHandle handle; const char *v4l2_name; if(device_name == NULL || !initialized) { print_libwebcam_error("Unable to open device. No name given or library not initialized."); return 0; } // Try to find the device with the given name. // Note: If the given name is a device path (e.g. /dev/video0), the V4L2 name // is simply generated by cutting off the '/dev/' part. If the given name // starts with 'video', it is taken as is. if(strstr(device_name, "/dev/video") == device_name) v4l2_name = &device_name[5]; else if(strstr(device_name, "video") == device_name) v4l2_name = device_name; else if(strstr(device_name, "subdev") == device_name) v4l2_name = device_name; else { print_libwebcam_error("Unable to open device '%s'. Unrecognized device name.", device_name); return 0; } Device *device = find_device_by_name(v4l2_name); if(device == NULL) { print_libwebcam_error("Unable to open device '%s'. Device not found.", device_name); return 0; } // Create a handle for the given device // TODO Race condition if delete_device is called here (via c_cleanup) handle = create_handle(device); return handle; } /** * Closes a device handle. * * @param hDevice a handle obtained from c_open_device() */ void c_close_device (CHandle hDevice) { if(!initialized) return; close_handle(hDevice); } /** * Enumerates all devices available in the system. * * Users must call c_init() prior to using this function. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * @param devices a pointer to a buffer that retrieves the list of devices * @param size a pointer to an integer that contains or receives the size * of the @a devices buffer * @param count a pointer to an integer that receives the number of devices * available. Can be NULL. If this argument is not NULL, the * device count is returned independent of whether or not the * buffer is large enough. * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_SYNC_ERROR if the synchronization structures could not be initialized * - #C_INVALID_ARG if no size pointer was given or if a size pointer was given * but no @a devices buffer was given * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough */ CResult c_enum_devices (CDevice *devices, unsigned int *size, unsigned int *count) { CResult ret = C_SUCCESS; if(!initialized) return C_INIT_ERROR; if(size == NULL) return C_INVALID_ARG; // Refresh the internal device list ret = refresh_device_list(); if(ret) return ret; if(lock_mutex(&device_list.mutex)) return C_SYNC_ERROR; // Return the required size if the given size is not large enough if(count) *count = device_list.count; int dynamics_length = get_devices_dynamics_length(); int req_size = device_list.count * sizeof(CDevice) + dynamics_length; if(req_size > *size) { *size = req_size; ret = C_BUFFER_TOO_SMALL; goto done; } if(device_list.count == 0) goto done; if(devices == NULL) { ret = C_INVALID_ARG; goto done; } // Loop through all devices and return a list of CDevice structs CDevice *current = devices; Device *elem = device_list.first; unsigned int dynamics_offset = device_list.count * sizeof(CDevice); while(elem) { // Copy the simple attributes memcpy(current, &elem->device, sizeof(elem->device)); // Copy the strings copy_string_to_buffer(¤t->shortName, elem->device.shortName, devices, &dynamics_offset); copy_string_to_buffer(¤t->name, elem->device.name, devices, &dynamics_offset); copy_string_to_buffer(¤t->driver, elem->device.driver, devices, &dynamics_offset); copy_string_to_buffer(¤t->location, elem->device.location, devices, &dynamics_offset); current++; elem = elem->next; } assert(dynamics_offset == req_size); done: unlock_mutex(&device_list.mutex); return ret; } /** * Returns information about a given camera device. * * The function returns information about a device specified using a device handle * obtained from c_open_device() or a string that would be recognized by the same * function. The @a hDevice and @a device_name arguments are mutually exclusive. * If both are specified, the handle is used. If the device name should be used, * @a hDevice should be set to zero. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * Specifying a size of sizeof(CDevice) + strlen(device_name) + 84 will usually * be enough. This information can be used to try receiving device information in * a statically allocated buffer first. The number comes from the field lengths * that V4L2 uses internally. There is no guarantee, however, that this does not * change in the future, so applications must be prepared to allocate more memory * if indicated by a return value of #C_BUFFER_TOO_SMALL. * * @param hDevice a handle obtained from c_open_device() * @param device_name a device name as accepted by c_open_device() * @param info a pointer to a buffer to receive the device information * @param size a pointer to an integer that contains or receives the size * of the @a info buffer * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_SYNC_ERROR if the synchronization structures could not be initialized * - #C_INVALID_ARG if no size pointer was given or if a size pointer was given * but no @a info buffer was given * - #C_INVALID_HANDLE if a non-zero invalid handle was specified * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough */ CResult c_get_device_info (CHandle hDevice, const char *device_name, CDevice *info, unsigned int *size) { CDevice *info_src; if(!initialized) return C_INIT_ERROR; if(size == NULL) return C_INVALID_ARG; // Look for the device if(hDevice) { // By device handle if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; info_src = &GET_HANDLE(hDevice).device->device; } else if(device_name) { // By device name Device *device = find_device_by_name(device_name); if(device == NULL) return C_NOT_FOUND; info_src = &device->device; } else { return C_INVALID_ARG; } // Return the required size if the given size is not large enough int dynamics_length = get_device_dynamics_length(info_src); int req_size = sizeof(*info_src) + dynamics_length; if(req_size > *size) { *size = req_size; return C_BUFFER_TOO_SMALL; } if(info == NULL) return C_INVALID_ARG; // Copy the simple values memcpy(info, info_src, sizeof(*info_src)); // Copy the strings unsigned int dynamics_offset = sizeof(*info_src); copy_string_to_buffer(&info->shortName, info_src->shortName, info, &dynamics_offset); copy_string_to_buffer(&info->name, info_src->name, info, &dynamics_offset); copy_string_to_buffer(&info->driver, info_src->driver, info, &dynamics_offset); copy_string_to_buffer(&info->location, info_src->location, info, &dynamics_offset); assert(dynamics_offset == req_size); return C_SUCCESS; } /* * Frame format enumeration */ /** * Enumerates all pixel formats supported by the given camera. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * @param hDevice a handle obtained from c_open_device() * @param formats a pointer to a buffer that retrieves the list of pixel formats * @param size a pointer to an integer that contains or receives the size * of the @a formats buffer * @param count a pointer to an integer that receives the number of pixel * formats supported. Can be NULL. If this argument is not NULL, * the device count is returned independent of whether or not * the buffer is large enough. * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no size pointer was given or if a size pointer was given * but no @a formats buffer was given * - #C_INVALID_DEVICE if the device could not be opened * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough * - #C_NO_MEMORY if no temporary memory could be allocated * - #C_V4L2_ERROR if a V4L2 error occurred during pixel format enumeration */ CResult c_enum_pixel_formats (CHandle hDevice, CPixelFormat *formats, unsigned int *size, unsigned int *count) { CResult ret = C_SUCCESS; int v4l2_dev; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(size == NULL) return C_INVALID_ARG; // Open the corresponding V4L2 device v4l2_dev = open_v4l2_device(device->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; // Run V4L2 pixel format enumeration typedef struct _PixelFormat { CPixelFormat format; struct _PixelFormat * next; } PixelFormat; PixelFormat *head = NULL, *tail = NULL; unsigned int req_size = 0, format_count = 0; struct v4l2_fmtdesc fmt; memset(&fmt, 0, sizeof(fmt)); fmt.index = 0; fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while(ioctl(v4l2_dev, VIDIOC_ENUM_FMT, &fmt) == 0) { PixelFormat *format = (PixelFormat *)malloc(sizeof(PixelFormat)); if(!format) { ret = C_NO_MEMORY; goto done; } memset(format, 0, sizeof(PixelFormat)); fmt.index++; // Copy the pixel format attributes sprintf(format->format.fourcc, "%c%c%c%c", fmt.pixelformat & 0xFF, (fmt.pixelformat >> 8) & 0xFF, (fmt.pixelformat >> 16) & 0xFF, (fmt.pixelformat >> 24) & 0xFF); format->format.name = strdup((char *)fmt.description); req_size += sizeof(CPixelFormat) + strlen(format->format.name) + 1; if(!get_mimetype_from_fourcc(&format->format.mimeType, fmt.pixelformat)) req_size += strlen(format->format.mimeType) + 1; else format->format.mimeType = NULL; format_count++; // Append the format to the list if(head == NULL) head = tail = format; else tail->next = format; tail = format; } if(errno != EINVAL) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } // Return the required size if the given size is not large enough if(count) *count = format_count; if(req_size > *size) { *size = req_size; ret = C_BUFFER_TOO_SMALL; goto done; } if(format_count == 0) goto done; if(formats == NULL) { ret = C_INVALID_ARG; goto done; } // Loop through the formats and return a list of CPixelFormat structs CPixelFormat *current = formats; PixelFormat *elem = head; unsigned int dynamics_offset = format_count * sizeof(CPixelFormat); while(elem) { // Copy the simple attributes memcpy(current, &elem->format, sizeof(elem->format)); // Copy the strings copy_string_to_buffer(¤t->name, elem->format.name, formats, &dynamics_offset); if(elem->format.mimeType) copy_string_to_buffer(¤t->mimeType, elem->format.mimeType, formats, &dynamics_offset); current++; elem = elem->next; } assert(dynamics_offset == req_size); done: // Free the list of pixel formats and close the V4L2 device close(v4l2_dev); elem = head; while(elem) { PixelFormat *next = elem->next; if(elem->format.mimeType) free(elem->format.mimeType); if(elem->format.name) free(elem->format.name); free(elem); elem = next; } return ret; } /** * Enumerates all frame sizes supported for the given pixel format. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * A list of pixel formats can be obtained from c_enum_pixel_formats(). * * @param hDevice a handle obtained from c_open_device() * @param pixelformat the pixel format for which the frame sizes should be * enumerated * @param sizes a pointer to a buffer that retrieves the list of frame sizes * @param size a pointer to an integer that contains or receives the size * of the @a sizes buffer * @param count a pointer to an integer that receives the number of frame * sizes supported for the given pixel format. Can be NULL. * If this argument is not NULL, the frame size count is * returned independent of whether or not the buffer is large * enough. * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no size pointer was given; if a size pointer was given * but no @a sizes buffer was given; if no @a pixelformat was given * - #C_INVALID_DEVICE if the device could not be opened * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough * - #C_NO_MEMORY if no temporary memory could be allocated * - #C_V4L2_ERROR if a V4L2 error occurred during frame size enumeration */ CResult c_enum_frame_sizes (CHandle hDevice, const CPixelFormat *pixelformat, CFrameSize *sizes, unsigned int *size, unsigned int *count) { CResult ret = C_SUCCESS; int v4l2_dev; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(size == NULL || pixelformat == NULL) return C_INVALID_ARG; // Open the corresponding V4L2 device v4l2_dev = open_v4l2_device(device->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; // Run V4L2 frame size enumeration typedef struct _FrameSize { CFrameSize size; struct _FrameSize * next; } FrameSize; FrameSize *head = NULL, *tail = NULL; unsigned int req_size = 0, size_count = 0; struct v4l2_frmsizeenum fsize; memset(&fsize, 0, sizeof(fsize)); fsize.index = 0; fsize.pixel_format = pixelformat->fourcc[0] | (unsigned long)pixelformat->fourcc[1] << 8 | (unsigned long)pixelformat->fourcc[2] << 16 | (unsigned long)pixelformat->fourcc[3] << 24; fsize.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while(ioctl(v4l2_dev, VIDIOC_ENUM_FRAMESIZES, &fsize) == 0) { FrameSize *framesize = (FrameSize *)malloc(sizeof(FrameSize)); if(!framesize) { ret = C_NO_MEMORY; goto done; } memset(framesize, 0, sizeof(FrameSize)); fsize.index++; // Copy the frame size attributes if(fsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { framesize->size.type = CF_SIZE_DISCRETE; framesize->size.width = fsize.discrete.width; framesize->size.height = fsize.discrete.height; } else if(fsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS) { framesize->size.type = CF_SIZE_CONTINUOUS; framesize->size.min_width = fsize.stepwise.min_width; framesize->size.max_width = fsize.stepwise.max_width; framesize->size.step_width = 1; framesize->size.min_height = fsize.stepwise.min_height; framesize->size.max_height = fsize.stepwise.max_height; framesize->size.step_height = 1; } else if(fsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { framesize->size.type = CF_SIZE_STEPWISE; framesize->size.min_width = fsize.stepwise.min_width; framesize->size.max_width = fsize.stepwise.max_width; framesize->size.step_width = fsize.stepwise.step_width; framesize->size.min_height = fsize.stepwise.min_height; framesize->size.max_height = fsize.stepwise.max_height; framesize->size.step_height = fsize.stepwise.step_height; } req_size += sizeof(CFrameSize); size_count++; // Append the frame size to the list if(head == NULL) head = tail = framesize; else tail->next = framesize; tail = framesize; } if(errno != EINVAL) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } // Return the required size if the given size is not large enough if(count) *count = size_count; if(req_size > *size) { *size = req_size; ret = C_BUFFER_TOO_SMALL; goto done; } if(size_count == 0) goto done; if(sizes == NULL) return C_INVALID_ARG; // Loop through the formats and return a list of CFrameSize structs CFrameSize *current = sizes; FrameSize *elem = head; while(elem) { memcpy(current, &elem->size, sizeof(elem->size)); current++; elem = elem->next; } done: // Free the list of frame sizes and close the V4L2 device close(v4l2_dev); elem = head; while(elem) { FrameSize *next = elem->next; free(elem); elem = next; } return ret; } /** * Enumerates all frame intervals supported for the given pixel format and frame size. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * A list of pixel formats can be obtained from c_enum_pixel_formats(). In a * similar manner the list of supported frame sizes for each pixel format can be * obtained from c_enum_frame_sizes(). * * @param hDevice a handle obtained from c_open_device() * @param pixelformat the pixel format for which the frame intervals should be * enumerated * @param framesize the frame size for which the frame intervals should be * enumerated. Note that this frame size's type must be discrete. * @param intervals a pointer to a buffer that retrieves the list of frame * intervals * @param size a pointer to an integer that contains or receives the size * of the @a intervals buffer * @param count a pointer to an integer that receives the number of frame * intervals supported for the given pixel format and frame * size. Can be NULL. If this argument is not NULL, the frame * size count is returned independent of whether or not the * buffer is large enough. * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no size pointer was given; if a size pointer was given * but no @a sizes buffer was given; if @a pixelformat or @a framesize were * not given; if a non-descrete frame size was given * - #C_INVALID_DEVICE if the device could not be opened * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough * - #C_NO_MEMORY if no temporary memory could be allocated * - #C_V4L2_ERROR if a V4L2 error occurred during frame interval enumeration */ CResult c_enum_frame_intervals (CHandle hDevice, const CPixelFormat *pixelformat, const CFrameSize *framesize, CFrameInterval *intervals, unsigned int *size, unsigned int *count) { CResult ret = C_SUCCESS; int v4l2_dev; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(size == NULL || pixelformat == NULL || framesize == NULL) return C_INVALID_ARG; // The frame size must be discrete because V4L2's VIDIOC_ENUM_FRAMEINTERVALS function // only accepts a single width and height. if(framesize->type != CF_SIZE_DISCRETE) return C_INVALID_ARG; // Open the corresponding V4L2 device v4l2_dev = open_v4l2_device(device->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; // Run V4L2 frame interval enumeration typedef struct _FrameInterval { CFrameInterval interval; struct _FrameInterval * next; } FrameInterval; FrameInterval *head = NULL, *tail = NULL; unsigned int req_size = 0, interval_count = 0; struct v4l2_frmivalenum fival; memset(&fival, 0, sizeof(fival)); fival.index = 0; fival.pixel_format = pixelformat->fourcc[0] | (unsigned long)pixelformat->fourcc[1] << 8 | (unsigned long)pixelformat->fourcc[2] << 16 | (unsigned long)pixelformat->fourcc[3] << 24; fival.width = framesize->width; fival.height = framesize->height; fival.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; while(ioctl(v4l2_dev, VIDIOC_ENUM_FRAMEINTERVALS, &fival) == 0) { FrameInterval *frameinterval = (FrameInterval *)malloc(sizeof(FrameInterval)); if(!frameinterval) { ret = C_NO_MEMORY; goto done; } memset(frameinterval, 0, sizeof(FrameInterval)); fival.index++; // Copy the frame interval attributes if(fival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { frameinterval->interval.type = CF_INTERVAL_DISCRETE; frameinterval->interval.n = fival.discrete.numerator; frameinterval->interval.d = fival.discrete.denominator; } else if(fival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS) { frameinterval->interval.type = CF_INTERVAL_CONTINUOUS; frameinterval->interval.min_n = fival.stepwise.min.numerator; frameinterval->interval.min_d = fival.stepwise.min.denominator; frameinterval->interval.max_n = fival.stepwise.max.numerator; frameinterval->interval.max_d = fival.stepwise.max.denominator; frameinterval->interval.step_n = 1; frameinterval->interval.step_d = 1; } else if(fival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { frameinterval->interval.type = CF_INTERVAL_STEPWISE; frameinterval->interval.min_n = fival.stepwise.min.numerator; frameinterval->interval.min_d = fival.stepwise.min.denominator; frameinterval->interval.max_n = fival.stepwise.max.numerator; frameinterval->interval.max_d = fival.stepwise.max.denominator; frameinterval->interval.step_n = fival.stepwise.step.numerator; frameinterval->interval.step_d = fival.stepwise.step.denominator; } req_size += sizeof(CFrameInterval); interval_count++; // Append the frame interval to the list if(head == NULL) head = tail = frameinterval; else tail->next = frameinterval; tail = frameinterval; } if(errno != EINVAL) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } // Return the required size if the given size is not large enough if(count) *count = interval_count; if(req_size > *size) { *size = req_size; ret = C_BUFFER_TOO_SMALL; goto done; } if(interval_count == 0) goto done; if(intervals == NULL) return C_INVALID_ARG; // Loop through the formats and return a list of CFrameInterval structs CFrameInterval *current = intervals; FrameInterval *elem = head; while(elem) { memcpy(current, &elem->interval, sizeof(elem->interval)); current++; elem = elem->next; } done: // Free the list of frame sizes and close the V4L2 device close(v4l2_dev); elem = head; while(elem) { FrameInterval *next = elem->next; free(elem); elem = next; } return ret; } /* * Controls */ /** * Enumerates all controls supported by the given device. * * If the buffer is not large enough, #C_BUFFER_TOO_SMALL is returned and * the \a size parameter is modified to contain the required buffer size. * * @param hDevice a device handle obtained from c_open_device() * @param controls a pointer to a buffer that retrieves the list of supported * controls. * @param size a pointer to an integer that contains or receives the size of * the \a controls buffer. * @param count a pointer to an integer that receives the number of controls * supported. Can be NULL. If this argument is not NULL, the control * count is returned independent of whether or not the buffer is * large enough. * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_SYNC_ERROR if the synchronization structures could not be initialized * - #C_INVALID_ARG if no size pointer was given or if a size pointer was given * but no @a controls buffer was given * - #C_BUFFER_TOO_SMALL if the supplied buffer is not large enough */ CResult c_enum_controls (CHandle hDevice, CControl *controls, unsigned int *size, unsigned int *count) { CResult ret = C_SUCCESS; unsigned int names_length, choices_length; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(size == NULL) return C_INVALID_ARG; if(lock_mutex(&device->controls.mutex)) return C_SYNC_ERROR; // Determine the buffer size needed to describe all controls if(count) *count = device->controls.count; get_control_dynamics_length(device, &names_length, &choices_length); int req_size = device->controls.count * sizeof(CControl) + names_length + choices_length; if(req_size > *size) { *size = req_size; ret = C_BUFFER_TOO_SMALL; goto done; } if(device->controls.count == 0) goto done; if(controls == NULL) return C_INVALID_ARG; // Loop through all the device's controls and return a list of CControl structs CControl *current = controls; Control *elem = device->controls.first; unsigned int names_offset = device->controls.count * sizeof(CControl); unsigned int choices_offset = names_offset + names_length; while(elem) { // Copy the simple attributes memcpy(current, &elem->control, sizeof(elem->control)); // Copy the name unsigned int name_length = strlen(elem->control.name); current->name = (char *)controls + names_offset; memcpy(current->name, elem->control.name, name_length + 1); assert(names_offset + name_length < req_size); names_offset += name_length + 1; // Copy the choices if(elem->control.type == CC_TYPE_CHOICE) { current->choices.count = elem->control.choices.count; current->choices.list = (CControlChoice *)((char *)controls + choices_offset); choices_offset += elem->control.choices.count * sizeof(CControlChoice); //current->choices.names = (char *)controls + choices_offset; int index; for(index = 0; index < elem->control.choices.count; index++) { int name_length = strlen(elem->control.choices.list[index].name); current->choices.list[index].index = elem->control.choices.list[index].index; memcpy(current->choices.list[index].name, elem->control.choices.list[index].name, name_length + 1); assert(choices_offset + name_length < req_size); choices_offset += name_length + 1; } } current++; elem = elem->next; } assert(choices_offset == req_size); done: unlock_mutex(&device->controls.mutex); return ret; } /** * Sets the value of a device control. * * @param hDevice a device handle obtained from c_open_device() * @param control_id the ID of the control whose value shall be set * @param value the value to which the control shall be set * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no value is given * - #C_NOT_FOUND if the device does not support the given control * - #C_CANNOT_WRITE if the given control is not writable * - #C_INVALID_DEVICE if the device could not be opened * - #C_V4L2_ERROR if a V4L2 error occurred during control access */ CResult c_set_control (CHandle hDevice, CControlId control_id, const CControlValue *value) { CResult ret = C_SUCCESS; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(value == NULL) return C_INVALID_ARG; // Look for the requested control within the given device Control *control = find_control_by_id(device, control_id); if(!control) return C_NOT_FOUND; // Check if the control is writable if(!(control->control.flags & CC_CAN_WRITE)) return C_CANNOT_WRITE; // Write the control in a way that depends on its source if(control->v4l2_control) { // V4L2 ret = write_v4l2_control(device, control, value, hDevice); } else { assert(0); return C_INVALID_ARG; } return ret; } /** * Returns the value of a device control. * * @param hDevice a device handle obtained from c_open_device() * @param control_id the ID of the control whose value shall be read * @param value a pointer to receive the value read * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no value is given * - #C_NOT_FOUND if the device does not support the given control * - #C_CANNOT_READ if the given control is not readable * - #C_INVALID_DEVICE if the device could not be opened * - #C_V4L2_ERROR if a V4L2 error occurred during control access */ CResult c_get_control (CHandle hDevice, CControlId control_id, CControlValue *value) { CResult ret = C_SUCCESS; // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(value == NULL) return C_INVALID_ARG; // Look for the requested control within the given device Control *control = find_control_by_id(device, control_id); if(!control) return C_NOT_FOUND; // Check if the control is readable if(!(control->control.flags & CC_CAN_READ)) return C_CANNOT_READ; // Read the control in a way that depends on its source if(control->v4l2_control) { // V4L2 ret = read_v4l2_control(device, control, value, hDevice); } else { assert(0); return C_INVALID_ARG; } return ret; } CResult c_read_xu_control(CHandle hDevice, unsigned char entity[], uint16_t unit_id, unsigned char selector, CControlValue *value) { static unsigned int last_uvc_ctrl_id = CC_UVC_XU_BASE; assert(last_uvc_ctrl_id < 0xFFFFFFFF); CResult ret = C_SUCCESS; Control *ctrl = NULL; // Create the name for the control. // We don't have a meaningful name here, so we make it up from the GUID and selector. char *name = NULL; int r = asprintf(&name, GUID_FORMAT"/%u", GUID_ARGS(entity), selector); if(r <= 0) { ret = C_NO_MEMORY; goto done; } // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; // Create the internal control info structure ctrl = (Control *)malloc(sizeof(*ctrl)); if(ctrl) { memset(ctrl, 0, sizeof(*ctrl)); ctrl->control.id = last_uvc_ctrl_id++; ctrl->uvc_unitid = unit_id; ctrl->uvc_selector = selector; ctrl->uvc_size = 0; // determined by init_xu_control() ctrl->control.name = name; ctrl->control.type = CC_TYPE_RAW; ctrl->control.flags = 0; // determined by init_xu_control() // Initialize the XU control (size, flags, min/max/def/res) ret = init_xu_control(device, ctrl); value->raw.data = malloc(ctrl->uvc_size); value->raw.size = ctrl->uvc_size; if(ret) goto done; ctrl->control.flags |= CC_IS_CUSTOM; ret = read_xu_control(device, ctrl, value, hDevice); } done: if(ret != C_SUCCESS && ctrl) { SAFE_FREE(ctrl->control.name); SAFE_FREE(ctrl); } return ret; } CResult c_write_xu_control(CHandle hDevice, unsigned char entity[], uint16_t unit_id, unsigned char selector, CControlValue *value) { static unsigned int last_uvc_ctrl_id = CC_UVC_XU_BASE; assert(last_uvc_ctrl_id < 0xFFFFFFFF); CResult ret = C_SUCCESS; Control *ctrl = NULL; // Create the name for the control. // We don't have a meaningful name here, so we make it up from the GUID and selector. char *name = NULL; int r = asprintf(&name, GUID_FORMAT"/%u", GUID_ARGS(entity), selector); if(r <= 0) { ret = C_NO_MEMORY; goto done; } // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; // Create the internal control info structure ctrl = (Control *)malloc(sizeof(*ctrl)); if(ctrl) { memset(ctrl, 0, sizeof(*ctrl)); ctrl->control.id = last_uvc_ctrl_id++; ctrl->uvc_unitid = unit_id; ctrl->uvc_selector = selector; ctrl->uvc_size = 0; // determined by init_xu_control() ctrl->control.name = name; ctrl->control.type = CC_TYPE_RAW; ctrl->control.flags = 0; // determined by init_xu_control() // Initialize the XU control (size, flags, min/max/def/res) ret = init_xu_control(device, ctrl); if(ret) goto done; if (value->raw.size < ctrl->uvc_size) { ret = C_INVALID_ARG; goto done; } ctrl->control.flags |= CC_IS_CUSTOM; ret = write_xu_control(device, ctrl, value, hDevice); } done: if(ret != C_SUCCESS && ctrl) { SAFE_FREE(ctrl->control.name); SAFE_FREE(ctrl); } return ret; } /** * refreshes the values of all device controls. * * @param hDevice a device handle obtained from c_open_device() * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid */ static CResult refresh_control_values(CHandle hDevice) { // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; int ret = C_SUCCESS; //update control values Control *current = device->controls.first; while(current) { ret = read_v4l2_control(device, current, ¤t->control.value, hDevice); if(ret != C_SUCCESS) print_libwebcam_error("Could not read control: 0x%08x.\n", current->v4l2_control); current = current->next; } return C_SUCCESS; } /** * set special auto controls (higher id) before setting manual counterparts. * * @param hDevice a device handle obtained from c_open_device() * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid */ static CResult set_special_auto_controls(CHandle hDevice) { // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; int ret = C_SUCCESS; //update control values Control *current = device->controls.first; while(current) { if( (current->v4l2_control == V4L2_CID_FOCUS_AUTO) || (current->v4l2_control == V4L2_CID_HUE_AUTO) ) { if(current->control.flags & CC_NEED_SET) { ret = write_v4l2_control(device, current, ¤t->control.value, hDevice); if(ret != C_SUCCESS) { print_libwebcam_error("Could not set control: 0x%08x.\n", current->v4l2_control); // update with the real value read_v4l2_control(device, current, ¤t->control.value, hDevice); } current->control.flags &= ~(CC_NEED_SET); //reset flag } } current = current->next; } return C_SUCCESS; } /** * set the values of all device controls. * * @param hDevice a device handle obtained from c_open_device() * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid */ static CResult set_control_values(CHandle hDevice) { // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; //make sure special auto controls have already been set int ret = set_special_auto_controls(hDevice); //update all other control values Control *current = device->controls.first; while(current) { if(current->control.flags & CC_NEED_SET) { ret = write_v4l2_control(device, current, ¤t->control.value, hDevice); if(ret != C_SUCCESS) { print_libwebcam_error("Could not set control: 0x%08x.\n", current->v4l2_control); // update with the real value read_v4l2_control(device, current, ¤t->control.value, hDevice); } current->control.flags &= ~(CC_NEED_SET); //reset flag } current = current->next; } return C_SUCCESS; } /** * Looks up the control with the given V4L2 ID for the given device. * * @return * - NULL if no corresponding control was found for the given device. * - Pointer to the control if it was found. */ static Control *find_control_by_v4l2_id (Device *dev, int id) { Control *elem = dev->controls.first; while(elem) { if(elem->v4l2_control == id) break; elem = elem->next; } return elem; } /** * Stores the values of all device controls into a file. * * @param hDevice a device handle obtained from c_open_device() * @param filename file name for storing the controls data * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid */ CResult c_save_controls (CHandle hDevice, const char *filename) { // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(lock_mutex(&device->controls.mutex)) return C_SYNC_ERROR; //printf("%i device controls\n",device->controls.count); FILE *fp = fopen(filename, "w"); if( fp == NULL ) { print_libwebcam_error("Could not open control data file for write: %s.\n", filename); return (-1); } else { refresh_control_values(hDevice); //write header fprintf(fp, "#V4L2/CTRL/0.0.2\n"); fprintf(fp, "APP{\"libwebcam\"}\n"); //write control data fprintf(fp, "# control data\n"); Control *current = device->controls.first; while(current) { //printf("printing control id: 0x%08x\n", current->v4l2_control); if(!(current->control.flags & (CC_CAN_READ | CC_CAN_WRITE))) { current = current->next; printf("jumping\n"); continue; } fprintf(fp, "#%s\n", current->control.name); switch(current->control.type) { #ifdef ENABLE_RAW_CONTROLS case CC_TYPE_RAW : fprintf(fp, "ID{0x%08x};CHK{%i:%i:1:0}=STR{\"%s\"}\n", current->v4l2_control, current->control.min.raw.size, current->control.min.raw.size, (char *) current->control.value.raw.data); break; #endif case CC_TYPE_CHOICE : //since we don't have real v4l2 maximum, minimum, step //use 1 for step, 0 for minimum and calculate maximum from choices.count //NOTE: although this should be valid for most cases, it's not necessarly true. fprintf(fp, "ID{0x%08x};CHK{0:%i:1:%i}=VAL{%i}\n", current->v4l2_control, current->control.choices.count - 1, current->control.def.value, current->control.value.value); break; default : fprintf(fp, "ID{0x%08x};CHK{%i:%i:%i:%i}=VAL{%i}\n", current->v4l2_control, current->control.min.value, current->control.max.value, current->control.step.value, current->control.def.value, current->control.value.value); break; } current = current->next; } } fclose(fp); unlock_mutex(&device->controls.mutex); return C_SUCCESS; } /** * Loads the values of all device controls from a file. * * @param hDevice a device handle obtained from c_open_device() * @param filename file name for reading the controls data * @return * - #C_SUCCESS on success * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_HANDLE if the given device handle is invalid * - #C_INVALID_ARG if no value is given * - #C_NOT_FOUND if the device does not support the given control * - #C_CANNOT_READ if the given control is not readable * - #C_INVALID_DEVICE if the device could not be opened * - #C_V4L2_ERROR if a V4L2 error occurred during control access */ CResult c_load_controls (CHandle hDevice, const char *filename) { // Check the given handle and arguments if(!initialized) return C_INIT_ERROR; if(!HANDLE_OPEN(hDevice)) return C_INVALID_HANDLE; if(!HANDLE_VALID(hDevice)) return C_NOT_EXIST; Device *device = GET_HANDLE(hDevice).device; if(lock_mutex(&device->controls.mutex)) return C_SYNC_ERROR; FILE *fp = fopen(filename, "r"); if( fp == NULL ) { print_libwebcam_error("Could not open control data file for read: %s.\n", filename); return (-1); } else { char line[200]; if(fgets(line, sizeof(line), fp) != NULL) { int major,minor,rev; if(sscanf(line,"#V4L2/CTRL/%i.%i.%i", &major, &minor, &rev) == 3) { //check standard version if needed } else { print_libwebcam_error("no valid control file header found\n"); goto finish; } } else { print_libwebcam_error("no valid control file header found\n"); goto finish; } while (fgets(line, sizeof(line), fp) != NULL) { int id = 0; int min = 0, max = 0, step = 0, def = 0; int32_t val = 0; //int64_t val64 = 0; if ((line[0]!='#') && (line[0]!='\n')) { if(sscanf(line,"ID{0x%08x};CHK{%i:%i:%i:%i}=VAL{%i}", &id, &min, &max, &step, &def, &val) == 6) { Control *current = find_control_by_v4l2_id(device, id); if(current) { //check values if((current->control.type != CC_TYPE_CHOICE && (current->control.min.value == min && current->control.max.value == max && current->control.step.value == step && current->control.def.value == def)) || (current->control.type == CC_TYPE_CHOICE && current->control.def.value == def)) { current->control.value.value = val; current->control.flags |= CC_NEED_SET; //set flag //printf("setting 0x%08x to %i\n", id, val); } else { print_libwebcam_error("control (0x%08x) - doesn't match hardware\n", id); } } } else if(sscanf(line,"ID{0x%08x};CHK{0:0:0:0}=VAL64{", &id) == 1) { print_libwebcam_error("control (0x%08x) - 64 bit controls not supported\n", id); } else if(sscanf(line,"ID{0x%08x};CHK{%i:%i:%i:0}=STR{\"%*s\"}", &id, &min, &max, &step) == 5) { #ifdef ENABLE_RAW_CONTROLS Control *current = find_control_by_v4l2_id(device, id); if(current) { //check values if(current->control.min.raw.size == min && current->control.max.raw.size == max && 1 == step) { char str[max+1]; sscanf(line, "ID{0x%*x};CHK{%*i:%*i:%*i:0}==STR{\"%s\"}", str); if(strlen(str) > max) //FIXME: should also check (minimum +N*step) { print_libwebcam_error("string bigger than maximum buffer size"); } else { strcpy(current->control.value.raw.data, str); current->control.flags |= CC_NEED_SET; //set flag } } } #endif } //else printf("skip line\n"); } } set_control_values(hDevice); } finish: fclose(fp); unlock_mutex(&device->controls.mutex); return C_SUCCESS; } /* * Events */ /** * Enumerates the events supported by the given device. @e [unimplemented] * * @return * - #C_INIT_ERROR if the library has not been initialized * - #C_NOT_IMPLEMENTED */ CResult c_enum_events (CHandle hDevice, CEvent *events, unsigned int *size, unsigned int *count) { if(!initialized) return C_INIT_ERROR; return C_NOT_IMPLEMENTED; } /** * Subscribes the caller to receive the given event. @e [unimplemented] * * @return * - #C_INIT_ERROR if the library has not been initialized * - #C_NOT_IMPLEMENTED */ CResult c_subscribe_event (CHandle hDevice, CEventId event_id, CEventHandler handler, void *context) { if(!initialized) return C_INIT_ERROR; return C_NOT_IMPLEMENTED; } /** * Unsubscribes the caller from the given event. @e [unimplemented] * * @return * - #C_INIT_ERROR if the library has not been initialized * - #C_NOT_IMPLEMENTED */ CResult c_unsubscribe_event (CHandle hDevice, CEventId event_id) { if(!initialized) return C_INIT_ERROR; return C_NOT_IMPLEMENTED; } /** * Returns the error message associated with a given error code. * * Note that the caller must free the buffer returned by this function. * * @param error error code for which the message should be retrieved * @return * - a newly allocated string describing the given error code * - NULL if not enough memory was available or if the error code is * unknown */ char *c_get_error_text (CResult error) { return c_get_handle_error_text(0, error); } /** * Returns the error message associated with a given error code and device handle. * * Note that the caller must free the buffer returned by this function. Compared to the * #c_get_error_text() function, this function can take the handle's last system error * into account. * * @param hDevice an open device handle. If this parameter is 0, the function behaves * exactly like #c_get_error_text(). * @param error error code for which the message should be retrieved * @return * - a newly allocated string describing the given error code * - NULL if not enough memory was available or if the error code is * unknown */ char *c_get_handle_error_text (CHandle hDevice, CResult error) { switch(error) { case C_SUCCESS: return strdup("Success"); case C_NOT_IMPLEMENTED: return strdup("The function is not implemented"); case C_INIT_ERROR: return strdup("Error during initialization or library not initialized"); case C_INVALID_ARG: return strdup("Invalid argument"); case C_INVALID_HANDLE: return strdup("Invalid handle"); case C_INVALID_DEVICE: return strdup("Invalid device or device cannot be opened"); case C_NOT_FOUND: return strdup("Object not found"); case C_BUFFER_TOO_SMALL: return strdup("Buffer too small"); case C_SYNC_ERROR: return strdup("Error during data synchronization"); case C_NO_MEMORY: return strdup("Out of memory"); case C_NO_HANDLES: return strdup("Out of handles"); case C_V4L2_ERROR: { char *text = NULL; if(hDevice && HANDLE_OPEN(hDevice)) { if(asprintf(&text, "A Video4Linux2 API call returned an unexpected error %d", GET_HANDLE(hDevice).last_system_error) == -1) text = NULL;; } if(!text) return strdup("A Video4Linux2 API call returned an unexpected error"); return text; } case C_SYSFS_ERROR: return strdup("A sysfs file access returned an error"); case C_PARSE_ERROR: return strdup("A control could not be parsed"); case C_CANNOT_WRITE: return strdup("Writing not possible (e.g. read-only control)"); case C_CANNOT_READ: return strdup("Reading not possible (e.g. write-only control)"); default: return NULL; } } /* * Helper functions */ /** * Prints a generic error message to stderr. */ void print_libwebcam_error (char *format, ...) { char *newformat; va_list ap; if(asprintf(&newformat, "[libwebcam] %s\n", format) == -1) newformat = format; va_start(ap, format); vfprintf(stderr, newformat, ap); va_end(ap); if(newformat != format) free(newformat); else fprintf(stderr, "\n"); } /** * Prints a libwebcam error message to stderr. * * @param error a #CResult error code whose error text is appended * @param format a @a printf compatible format */ static void print_libwebcam_c_error (CResult error, char *format, ...) { char *unknown_text = "Unknown error"; char *text, *newformat; va_list ap; // Retrieve the libwebcam error text text = c_get_error_text(error); if(text == NULL) text = unknown_text; if(asprintf(&newformat, "[libwebcam] %s (error %d: %s)\n", format, error, text) == -1) newformat = format; if(text != unknown_text) free(text); va_start(ap, format); vfprintf(stderr, newformat, ap); va_end(ap); if(newformat != format) free(newformat); else fprintf(stderr, "\n"); } /* * Control management */ /** * Queries the control choice values of the given V4L2 control and uses the results to * fill in the choice structures of a libwebcam control. * * @param ctrl Internal control for which the choice data is requested. * @param v4l2_ctrl Pointer to a structure obtained from VIDIOC_QUERYCTRL and containing * the V4L2 control data. * @param v4l2_dev Open V4L2 device handle. */ static CResult create_control_choices (Control *ctrl, struct v4l2_queryctrl *v4l2_ctrl, int v4l2_dev) { CResult ret = C_SUCCESS; //int choices_count = v4l2_ctrl->maximum - v4l2_ctrl->minimum + 1; ctrl->control.choices.count = 0; ctrl->control.choices.list = NULL; // Allocate memory for the choices.names and choices.list members //ctrl->control.choices.names = (char *)malloc(choices_count * V4L2_MENU_CTRL_MAX_NAME_SIZE); //if(ctrl->control.choices.names == NULL) { // ret = C_NO_MEMORY; // goto done; //} //ctrl->control.choices.list = (CControlChoice *)malloc(choices_count * sizeof(CControlChoice)); //if(ctrl->control.choices.list == NULL) { // ret = C_NO_MEMORY; // goto done; //} // Query the menu items of the given control and transform them // into CControlChoice. struct v4l2_querymenu v4l2_menu = {0}; v4l2_menu.id = v4l2_ctrl->id; for(v4l2_menu.index = v4l2_ctrl->minimum; v4l2_menu.index <= v4l2_ctrl->maximum; v4l2_menu.index++) { if(ioctl(v4l2_dev, VIDIOC_QUERYMENU, &v4l2_menu) < 0) continue; ctrl->control.choices.count++; if(!ctrl->control.choices.list) ctrl->control.choices.list = (CControlChoice *)malloc(sizeof(CControlChoice)); else ctrl->control.choices.list = (CControlChoice *)realloc(ctrl->control.choices.list, ctrl->control.choices.count * sizeof(CControlChoice)); ctrl->control.choices.list[ctrl->control.choices.count-1].index = v4l2_menu.index; ctrl->control.choices.list[ctrl->control.choices.count-1].id = v4l2_menu.id; if(strlen((char *)v4l2_menu.name)) memcpy(ctrl->control.choices.list[ctrl->control.choices.count-1].name, v4l2_menu.name, V4L2_MENU_CTRL_MAX_NAME_SIZE); else snprintf(ctrl->control.choices.list[ctrl->control.choices.count-1].name, V4L2_MENU_CTRL_MAX_NAME_SIZE, "%d", v4l2_menu.index); } if(ret != C_SUCCESS) { if(ctrl->control.choices.list) free(ctrl->control.choices.list); } return ret; } /** * Create a libwebcam control from a V4L2 control. * * If necessary, further information is requested by this function, e.g. in the case * of a choice control. * * @param device Device to which the control should be appended. * @param v4l2_ctrl Pointer to a structure obtained from VIDIOC_QUERYCTRL and containing * the V4L2 control data. * @param v4l2_dev Open V4L2 device handle. * @param pret Pointer to receive the error code in the case of an error. * (Can be NULL.) * * @return * - NULL if an error occurred. The associated error can be found in @a pret. * - Pointer to the newly created control. */ static Control *create_v4l2_control (Device *device, struct v4l2_queryctrl *v4l2_ctrl, int v4l2_dev, CResult *pret) { CResult ret = C_SUCCESS; Control *ctrl = NULL; // Map V4L2 control types to libwebcam control types CControlType type; switch(v4l2_ctrl->type) { case V4L2_CTRL_TYPE_INTEGER: type = CC_TYPE_DWORD; break; case V4L2_CTRL_TYPE_BOOLEAN: type = CC_TYPE_BOOLEAN; break; case V4L2_CTRL_TYPE_MENU: type = CC_TYPE_CHOICE; break; #ifdef ENABLE_RAW_CONTROLS case V4L2_CTRL_TYPE_STRING: type = CC_TYPE_RAW; break; #endif case V4L2_CTRL_TYPE_BUTTON: type = CC_TYPE_BUTTON; break; case V4L2_CTRL_TYPE_INTEGER64: // TODO implement ret = C_NOT_IMPLEMENTED; print_libwebcam_error("Warning: Unsupported V4L2 control type encountered: ctrl_id = 0x%08X, " "name = '%s', type = %d", v4l2_ctrl->id, v4l2_ctrl->name, v4l2_ctrl->type); goto done; default: ret = C_PARSE_ERROR; print_libwebcam_error("Invalid V4L2 control type encountered: ctrl_id = 0x%08X, " "name = '%s', type = %d", v4l2_ctrl->id, v4l2_ctrl->name, v4l2_ctrl->type); goto done; } // Map the V4L2 control ID to a libwebcam ID CControlId ctrl_id = get_control_id_from_v4l2(v4l2_ctrl->id, device); //printf("Mapping V4L2 control ID 0x%08X => 0x%08X\n", v4l2_ctrl->id, ctrl_id); if(ctrl_id == 0) { ret = C_NOT_IMPLEMENTED; goto done; } // Create the internal control info structure ctrl = (Control *)malloc(sizeof(*ctrl)); if(ctrl) { memset(ctrl, 0, sizeof(*ctrl)); ctrl->control.id = ctrl_id; ctrl->v4l2_control = v4l2_ctrl->id; if(strlen((char *)v4l2_ctrl->name)) ctrl->control.name = strdup((char *)v4l2_ctrl->name); else ctrl->control.name = strdup(UNKNOWN_CONTROL_NAME); ctrl->control.type = type; ctrl->control.flags = CC_CAN_READ; if(!(v4l2_ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)) ctrl->control.flags |= CC_CAN_WRITE; if(v4l2_ctrl->id >= V4L2_CID_PRIVATE_BASE) ctrl->control.flags |= CC_IS_CUSTOM; ctrl->control.def.value = v4l2_ctrl->default_value; // Process V4L2 menu-style and raw controls if(type == CC_TYPE_CHOICE) { ret = create_control_choices(ctrl, v4l2_ctrl, v4l2_dev); if(ret) goto done; } #ifdef ENABLE_RAW_CONTROLS else if(type == CC_TYPE_RAW) { if(v4l2_ctrl->minimum != v4l2_ctrl->maximum || v4l2_ctrl->step != 1) { print_libwebcam_error("Unsupported V4L2 string control encountered: ctrl_id = 0x%08X, " "name = '%s', min = %u, max = %u, step = %u", v4l2_ctrl->id, v4l2_ctrl->name, v4l2_ctrl->minimum, v4l2_ctrl->maximum, v4l2_ctrl->step); ret = C_NOT_IMPLEMENTED; goto done; } ctrl->control.value.raw.size = ctrl->control.min.raw.size = ctrl->control.def.raw.size = v4l2_ctrl->maximum; //allocate data buffer ctrl->control.value.raw.data = calloc(ctrl->control.def.raw.size, sizeof(char)); } #endif else { ctrl->control.min.value = v4l2_ctrl->minimum; ctrl->control.max.value = v4l2_ctrl->maximum; ctrl->control.step.value = v4l2_ctrl->step; } ctrl->next = NULL; // Add the new control to the end of the control list of the given device if(device->controls.last) { device->controls.last->next = ctrl; device->controls.last = device->controls.last->next; } else { // is the first control to be added device->controls.first = ctrl; device->controls.last = device->controls.first; } device->controls.count++; } else { ret = C_NO_MEMORY; } done: if(ret != C_SUCCESS && ctrl) { if(ctrl->control.name) { free(ctrl->control.name); ctrl->control.name = NULL; } free(ctrl); ctrl = NULL; } if(pret) *pret = ret; return ctrl; } /** * Frees all resources associated with the given control, including choice data. * * Note that this functino does not remove the control from its device's control list. */ static void delete_control (Control *ctrl) { if(ctrl->control.type == CC_TYPE_CHOICE) { if(ctrl->control.choices.list) free(ctrl->control.choices.list); //if(ctrl->control.choices.names) // free(ctrl->control.choices.names); } #ifdef ENABLE_RAW_CONTROLS if(ctrl->control.type == CC_TYPE_RAW) { if(ctrl->control.value.raw.data) free(ctrl->control.value.raw.data); } #endif if(ctrl->control.name) free(ctrl->control.name); free(ctrl); } /** * Looks up the control with the given ID for the given device. * * @return * - NULL if no corresponding control was found for the given device. * - Pointer to the control if it was found. */ static Control *find_control_by_id (Device *dev, CControlId id) { Control *elem = dev->controls.first; while(elem) { if(elem->control.id == id) break; elem = elem->next; } return elem; } /** * Clears the control list of the given device and frees all associated resources. */ static void clear_control_list (Device *dev) { lock_mutex(&dev->controls.mutex); Control *elem = dev->controls.first; while(elem) { Control *next = elem->next; delete_control(elem); elem = next; } dev->controls.first = NULL; dev->controls.count = 0; unlock_mutex(&dev->controls.mutex); } /** * Scans the given device for supported controls and adds them to the internal list. * * Note that this function clears all existing controls prior to reenumerating them. */ static CResult refresh_control_list (Device *dev) { CResult ret = C_SUCCESS; int v4l2_dev; struct v4l2_queryctrl v4l2_ctrl = { 0 }; // Clear control list first clear_control_list(dev); // Open the corresponding V4L2 device v4l2_dev = open_v4l2_device(dev->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; if(lock_mutex(&dev->controls.mutex)) { ret = C_SYNC_ERROR; goto done; } // Test if the driver supports the V4L2_CTRL_FLAG_NEXT_CTRL flag #ifdef ENABLE_V4L2_ADVANCED_CONTROL_ENUMERATION v4l2_ctrl.id = 0 | V4L2_CTRL_FLAG_NEXT_CTRL; if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl) == 0) { // The driver supports the V4L2_CTRL_FLAG_NEXT_CTRL flag, so go ahead with // the advanced enumeration way. int r; v4l2_ctrl.id = 0; int current_ctrl = v4l2_ctrl.id; v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; // Loop as long as ioctl does not return EINVAL while((r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)), r ? errno != EINVAL : 1) { #ifdef CONTROL_IO_ERROR_RETRIES if(r && (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)) { // An I/O error occurred, so retry the query a few times. // This part is a little tricky. On the one hand, we want to retrieve the ID // of the next control in case the query succeeds or we give up on retrying. // On the other hand we want to retry the erroneous control instead of just // skipping to the next one, wo we needed to backup the ID of the failing // control first (above in current_ctrl). // Keep in mind that with the NEXT_CTRL flag VIDIO_QUERYCTRL returns the // first control with a *higher* ID than the specified one. int tries = CONTROL_IO_ERROR_RETRIES; v4l2_ctrl.id = current_ctrl | V4L2_CTRL_FLAG_NEXT_CTRL; while(tries-- && (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) && (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)) { v4l2_ctrl.id = current_ctrl | V4L2_CTRL_FLAG_NEXT_CTRL; } } #endif // Prevent infinite loops for buggy NEXT_CTRL implementations if(r && v4l2_ctrl.id <= current_ctrl) { // If there was an error but the driver failed to provide us with the ID // of the next control, we have to manually increase the control ID, // otherwise we risk getting stuck querying the erroneous control. current_ctrl++; print_libwebcam_error( "Warning: The driver behind device %s has a slightly buggy implementation\n" " of the V4L2_CTRL_FLAG_NEXT_CTRL flag. It does not return the next higher\n" " control ID if a control query fails. A workaround has been enabled.", dev->v4l2_name); goto next_control; } else if(!r && v4l2_ctrl.id == current_ctrl) { // If there was no error but the driver did not increase the control ID // we simply cancel the enumeration. print_libwebcam_error( "Error: The driver %s behind device %s has a buggy\n" " implementation of the V4L2_CTRL_FLAG_NEXT_CTRL flag. It does not raise an\n" " error or return the next control. Canceling control enumeration.", dev->device.driver, dev->v4l2_name); goto done; } current_ctrl = v4l2_ctrl.id; // Skip failed and disabled controls if(r || v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) goto next_control; Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret); if(ctrl == NULL) { if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) { print_libwebcam_error("Invalid or unsupported V4L2 control encountered: " "ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name); ret = C_SUCCESS; } else { goto done; } } next_control: v4l2_ctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL; } } else #endif { // The driver does not support the V4L2_CTRL_FLAG_NEXT_CTRL flag, so we need // to fall back to the old way of enumerating controls, i.e. enumerating the // standard V4L2 controls first, followed by the driver's private controls. // It won't be possible to enumerate controls with non-contiguous IDs but in // this case the driver probably doesn't implement any. // Enumerate default V4L2 controls. // We use a separate variable instead of v4l2_ctrl.id for the loop counter because // some drivers (bttv) simply return a fake control with ID 0 when the device // doesn't support a control in the [V4L2_CID_BASE, V4L2_CID_LASTP1) interval, // thereby overwriting our loop variable and causing us to restart from 0. int current_ctrl; for(current_ctrl = V4L2_CID_BASE; current_ctrl < V4L2_CID_LASTP1; current_ctrl++) { v4l2_ctrl.id = current_ctrl; #ifndef CONTROL_IO_ERROR_RETRIES if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl) || v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; #else int r = 0, tries = 1 + CONTROL_IO_ERROR_RETRIES; while(tries-- && (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) && (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)); if(r || v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; #endif Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret); if(ctrl == NULL) { if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) { print_libwebcam_error("Invalid or unsupported V4L2 control encountered: " "ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name); ret = C_SUCCESS; continue; } goto done; } } // Enumerate custom controls for(v4l2_ctrl.id = V4L2_CID_PRIVATE_BASE;; v4l2_ctrl.id++) { #ifndef CONTROL_IO_ERROR_RETRIES if(ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) break; #else int r = 0, tries = 1 + CONTROL_IO_ERROR_RETRIES; while(tries-- && (r = ioctl(v4l2_dev, VIDIOC_QUERYCTRL, &v4l2_ctrl)) && (errno == EIO || errno == EPIPE || errno == ETIMEDOUT)); if(r) break; #endif if(v4l2_ctrl.flags & V4L2_CTRL_FLAG_DISABLED) continue; Control *ctrl = create_v4l2_control(dev, &v4l2_ctrl, v4l2_dev, &ret); if(ctrl == NULL) { if(ret == C_PARSE_ERROR || ret == C_NOT_IMPLEMENTED) { print_libwebcam_error("Invalid or unsupported custom V4L2 control encountered: " "ctrl_id = 0x%08X, name = '%s'", v4l2_ctrl.id, v4l2_ctrl.name); ret = C_SUCCESS; continue; } goto done; } } } done: unlock_mutex(&dev->controls.mutex); close(v4l2_dev); return ret; } /** * Retrieve device information for the given device. */ static CResult refresh_device_details (Device *dev) { CResult ret = C_SUCCESS; int v4l2_dev; struct v4l2_capability v4l2_cap; // Open the corresponding V4L2 device v4l2_dev = open_v4l2_device(dev->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; // Query the device if(!ioctl(v4l2_dev, VIDIOC_QUERYCAP, &v4l2_cap)) { if(v4l2_cap.card[0]) dev->device.name = strdup((char *)v4l2_cap.card); else dev->device.name = dev->v4l2_name; // strdup?! dev->device.driver = strdup((char *)v4l2_cap.driver); if(v4l2_cap.bus_info[0]) dev->device.location = strdup((char *)v4l2_cap.bus_info); else dev->device.location = dev->v4l2_name; // strdup?! } else { //ret = C_V4L2_ERROR; dev->device.name = strdup(dev->v4l2_name); dev->device.driver = strdup("uvcvideo"); dev->device.location = strdup(dev->v4l2_name); } close(v4l2_dev); return ret; } /** * Returns the length required to store all the (null-terminated) names of the given * device's controls in a buffer. * * Note: The control list should be locked before calling this function. */ static unsigned int get_control_dynamics_length(Device *device, unsigned int *names_length, unsigned int *choices_length) { unsigned int names = 0, choices = 0; Control *elem = device->controls.first; while(elem) { // Add length of the control name if(elem->control.name) names += strlen(elem->control.name) + 1; // Add length of the control choice names if(elem->control.type == CC_TYPE_CHOICE) { int index; for(index = 0; index < elem->control.choices.count; index++) { choices += sizeof(CControlChoice); choices += strlen(elem->control.choices.list[index].name) + 1; } } elem = elem->next; } if(names_length) *names_length = names; if(choices_length) *choices_length = choices; return names + choices; } /** * Converts a V4L2 control ID to a libwebcam control ID. * * @param v4l2_id V4L2 ID that should be converted. * @param dev Pointer to the device to which the control belongs. */ static CControlId get_control_id_from_v4l2 (int v4l2_id, Device *dev) { switch(v4l2_id) { // Basic V4L2 controls case V4L2_CID_BRIGHTNESS: return CC_BRIGHTNESS; case V4L2_CID_CONTRAST: return CC_CONTRAST; case V4L2_CID_SATURATION: return CC_SATURATION; case V4L2_CID_HUE: return CC_HUE; case V4L2_CID_AUDIO_VOLUME: break; // not supported by libwebcam case V4L2_CID_AUDIO_BALANCE: break; // not supported by libwebcam case V4L2_CID_AUDIO_BASS: break; // not supported by libwebcam case V4L2_CID_AUDIO_TREBLE: break; // not supported by libwebcam case V4L2_CID_AUDIO_MUTE: break; // not supported by libwebcam case V4L2_CID_AUDIO_LOUDNESS: break; // not supported by libwebcam case V4L2_CID_BLACK_LEVEL: break; // deprecated case V4L2_CID_AUTO_WHITE_BALANCE: return CC_AUTO_WHITE_BALANCE_TEMPERATURE; case V4L2_CID_DO_WHITE_BALANCE: break; // not supported by libwebcam case V4L2_CID_RED_BALANCE: break; // not supported by libwebcam case V4L2_CID_BLUE_BALANCE: break; // not supported by libwebcam case V4L2_CID_GAMMA: return CC_GAMMA; case V4L2_CID_EXPOSURE: return CC_EXPOSURE_TIME_ABSOLUTE; case V4L2_CID_AUTOGAIN: break; // not supported by libwebcam case V4L2_CID_GAIN: return CC_GAIN; case V4L2_CID_HFLIP: break; // not supported by libwebcam case V4L2_CID_VFLIP: break; // not supported by libwebcam #ifdef V4L2_CID_POWER_LINE_FREQUENCY case V4L2_CID_POWER_LINE_FREQUENCY: return CC_POWER_LINE_FREQUENCY; #endif #ifdef V4L2_CID_HUE_AUTO case V4L2_CID_HUE_AUTO: return CC_AUTO_HUE; #endif #ifdef V4L2_CID_WHITE_BALANCE_TEMPERATURE case V4L2_CID_WHITE_BALANCE_TEMPERATURE: return CC_WHITE_BALANCE_TEMPERATURE; #endif #ifdef V4L2_CID_SHARPNESS case V4L2_CID_SHARPNESS: return CC_SHARPNESS; #endif #ifdef V4L2_CID_BACKLIGHT_COMPENSATION case V4L2_CID_BACKLIGHT_COMPENSATION: return CC_BACKLIGHT_COMPENSATION; #endif #ifdef V4L2_CID_CHROMA_AGC case V4L2_CID_CHROMA_AGC: break; // not supported by libwebcam #endif #ifdef V4L2_CID_COLOR_KILLER case V4L2_CID_COLOR_KILLER: break; // not supported by libwebcam #endif #ifdef V4L2_CID_COLORFX case V4L2_CID_COLORFX: break; // not supported by libwebcam #endif #ifdef V4L2_CID_AUTOBRIGHTNESS case V4L2_CID_AUTOBRIGHTNESS: return CC_AUTO_BRIGHTNESS; // not supported by libwebcam #endif #ifdef V4L2_CID_BAND_STOP_FILTER case V4L2_CID_BAND_STOP_FILTER: break; // not supported by libwebcam #endif #ifdef V4L2_CID_ROTATE case V4L2_CID_ROTATE: break; // not supported by libwebcam #endif #ifdef V4L2_CID_BG_COLOR case V4L2_CID_BG_COLOR: break; // not supported by libwebcam #endif #ifdef V4L2_CID_CHROMA_GAIN case V4L2_CID_CHROMA_GAIN: break; // not supported by libwebcam #endif // Camera type controls #ifdef V4L2_CID_EXPOSURE_AUTO case V4L2_CID_EXPOSURE_AUTO: return CC_AUTO_EXPOSURE_MODE; #endif #ifdef V4L2_CID_EXPOSURE_ABSOLUTE case V4L2_CID_EXPOSURE_ABSOLUTE: return CC_EXPOSURE_TIME_ABSOLUTE; #endif #ifdef V4L2_CID_EXPOSURE_AUTO_PRIORITY case V4L2_CID_EXPOSURE_AUTO_PRIORITY: return CC_AUTO_EXPOSURE_PRIORITY; #endif #ifdef V4L2_CID_PAN_RELATIVE case V4L2_CID_PAN_RELATIVE: return CC_PAN_RELATIVE; #endif #ifdef V4L2_CID_TILT_RELATIVE case V4L2_CID_TILT_RELATIVE: return CC_TILT_RELATIVE; #endif #ifdef V4L2_CID_PAN_RESET case V4L2_CID_PAN_RESET: return CC_PAN_RESET; #endif #ifdef V4L2_CID_TILT_RESET case V4L2_CID_TILT_RESET: return CC_TILT_RESET; #endif #ifdef V4L2_CID_PAN_ABSOLUTE case V4L2_CID_PAN_ABSOLUTE: return CC_PAN_ABSOLUTE; #endif #ifdef V4L2_CID_TILT_ABSOLUTE case V4L2_CID_TILT_ABSOLUTE: return CC_TILT_ABSOLUTE; #endif #ifdef V4L2_CID_FOCUS_ABSOLUTE case V4L2_CID_FOCUS_ABSOLUTE: return CC_FOCUS_ABSOLUTE; #endif #ifdef V4L2_CID_FOCUS_RELATIVE case V4L2_CID_FOCUS_RELATIVE: return CC_FOCUS_RELATIVE; #endif #ifdef V4L2_CID_FOCUS_AUTO case V4L2_CID_FOCUS_AUTO: return CC_AUTO_FOCUS; #endif #ifdef V4L2_CID_ZOOM_ABSOLUTE case V4L2_CID_ZOOM_ABSOLUTE: return CC_ZOOM_ABSOLUTE; #endif #ifdef V4L2_CID_ZOOM_RELATIVE case V4L2_CID_ZOOM_RELATIVE: return CC_ZOOM_RELATIVE; #endif #ifdef V4L2_CID_ZOOM_CONTINUOUS case V4L2_CID_ZOOM_CONTINUOUS: break; // not supported by libwebcam #endif #ifdef V4L2_CID_PRIVACY case V4L2_CID_PRIVACY: return CC_PRIVACY; #endif #ifdef V4L2_CID_IRIS_ABSOLUTE case V4L2_CID_IRIS_ABSOLUTE: return CC_IRIS_ABSOLUTE; #endif #ifdef V4L2_CID_IRIS_RELATIVE case V4L2_CID_IRIS_RELATIVE: return CC_IRIS_RELATIVE; #endif #ifdef V4L2_CID_LED1_MODE case V4L2_CID_LED1_MODE: return CC_LOGITECH_LED1_MODE; #endif #ifdef V4L2_CID_LED1_FREQUENCY case V4L2_CID_LED1_FREQUENCY: return CC_LOGITECH_LED1_FREQUENCY; #endif #ifdef V4L2_CID_DISABLE_PROCESSING case V4L2_CID_DISABLE_PROCESSING: return CC_LOGITECH_DISABLE_PROCESSING; #endif #ifdef V4L2_CID_RAW_BITS_PER_PIXEL case V4L2_CID_RAW_BITS_PER_PIXEL: return CC_LOGITECH_RAW_BITS_PER_PIXEL; #endif #ifdef V4L2_CID_USB_VID case V4L2_CID_USB_VID return CC_LOGITECH_USB_VID; #endif #ifdef V4L2_CID_USB_PID case V4L2_CID_USB_PID return CC_LOGITECH_USB_PID; #endif #ifdef V4L2_CID_USB_BCD case V4L2_CID_USB_BCD return CC_LOGITECH_USB_BCD; #endif }; #ifdef USE_UVCVIDEO // Controls contained only in older UVC drivers //printf("*** 0x%08X 0x%08X\n", v4l2_id, UVC_CID_EXPOSURE_AUTO); if(strcmp(dev->device.driver, "uvcvideo") == 0) { switch(v4l2_id) { #ifdef UVC_CID_BACKLIGHT_COMPENSATION case UVC_CID_BACKLIGHT_COMPENSATION: return CC_BACKLIGHT_COMPENSATION; #endif #ifdef UVC_CID_POWER_LINE_FREQUENCY case UVC_CID_POWER_LINE_FREQUENCY: return CC_POWER_LINE_FREQUENCY; #endif #ifdef UVC_CID_SHARPNESS case UVC_CID_SHARPNESS: return CC_SHARPNESS; #endif #ifdef UVC_CID_HUE_AUTO case UVC_CID_HUE_AUTO: return CC_AUTO_HUE; #endif #ifdef UVC_CID_FOCUS_AUTO case UVC_CID_FOCUS_AUTO: return CC_AUTO_FOCUS; #endif #ifdef UVC_CID_FOCUS_ABSOLUTE case UVC_CID_FOCUS_ABSOLUTE: return CC_FOCUS_ABSOLUTE; #endif #ifdef UVC_CID_FOCUS_RELATIVE case UVC_CID_FOCUS_RELATIVE: return CC_FOCUS_RELATIVE; #endif #ifdef UVC_CID_PAN_RELATIVE case UVC_CID_PAN_RELATIVE: return CC_PAN_RELATIVE; #endif #ifdef UVC_CID_TILT_RELATIVE case UVC_CID_TILT_RELATIVE: return CC_TILT_RELATIVE; #endif #ifdef UVC_CID_PANTILT_RESET case UVC_CID_PANTILT_RESET: return CC_LOGITECH_PANTILT_RESET; #endif #ifdef UVC_CID_EXPOSURE_AUTO case UVC_CID_EXPOSURE_AUTO: return CC_AUTO_EXPOSURE_MODE; #endif #ifdef UVC_CID_EXPOSURE_ABSOLUTE case UVC_CID_EXPOSURE_ABSOLUTE: return CC_EXPOSURE_TIME_ABSOLUTE; #endif #ifdef UVC_CID_EXPOSURE_AUTO_PRIORITY case UVC_CID_EXPOSURE_AUTO_PRIORITY: return CC_AUTO_EXPOSURE_PRIORITY; #endif #ifdef UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO case UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO: return CC_AUTO_WHITE_BALANCE_TEMPERATURE; #endif #ifdef UVC_CID_WHITE_BALANCE_TEMPERATURE case UVC_CID_WHITE_BALANCE_TEMPERATURE: return CC_WHITE_BALANCE_TEMPERATURE; #endif #ifdef V4L2_CID_PANTILT_RELATIVE case V4L2_CID_PANTILT_RELATIVE: return CC_LOGITECH_PANTILT_RELATIVE; #endif } } #endif // Unknown V4L2 controls // Note that there is a margin of 256 control values for controls that are added // after libwebcam compilation time. if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_USER) { // Unknown user control print_libwebcam_error( "Unknown V4L2 user control ID encountered: 0x%08X (V4L2_CID_USER_BASE + %d)", v4l2_id, v4l2_id - V4L2_CID_USER_BASE ); return CC_V4L2_BASE + (v4l2_id - V4L2_CID_USER_BASE); } else if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_MPEG) { // Unknown MPEG control print_libwebcam_error( "Unknown V4L2 MPEG control ID encountered: 0x%08X (V4L2_CID_MPEG_BASE + %d)", v4l2_id, v4l2_id - V4L2_CID_MPEG_BASE ); return CC_V4L2_MPEG_BASE + (v4l2_id - V4L2_CID_MPEG_BASE); } else if(V4L2_CTRL_ID2CLASS(v4l2_id) == V4L2_CTRL_CLASS_CAMERA) { // Unknown camera class (UVC) control print_libwebcam_error( "Unknown V4L2 camera class (UVC) control ID encountered: 0x%08X (V4L2_CID_CAMERA_CLASS_BASE + %d)", v4l2_id, v4l2_id - V4L2_CID_CAMERA_CLASS_BASE ); return CC_V4L2_CAMERA_CLASS_BASE + (v4l2_id - V4L2_CID_CAMERA_CLASS_BASE); } else if(v4l2_id >= V4L2_CID_PRIVATE_BASE) { // Unknown private control print_libwebcam_error( "Unknown V4L2 private control ID encountered: 0x%08X (V4L2_CID_PRIVATE_BASE + %d)", v4l2_id, v4l2_id - V4L2_CID_PRIVATE_BASE ); return CC_V4L2_CUSTOM_BASE + (v4l2_id - V4L2_CID_PRIVATE_BASE); } print_libwebcam_error("Unknown V4L2 control ID encountered: 0x%08X", v4l2_id); return 0; } /* * Device management */ /** * Allocate a new device with the given name and add it to the global device list. */ static Device *create_device (char *name) { Device *dev = NULL; dev = (Device *)malloc(sizeof(*dev)); if(dev) { memset(dev, 0, sizeof(*dev)); strcpy(dev->v4l2_name, name); dev->device.shortName = strdup(name); dev->valid = 1; // Add the new device to the global device list dev->next = device_list.first; device_list.first = dev; device_list.count++; } return dev; } /** * Free up the given device. * * Note that this function does not remove the device from the global device list. */ static void delete_device (Device *dev) { // Free all the handles that point to this device lock_mutex(&handle_list.mutex); if(dev->handles > 0) { CHandle hDevice; for(hDevice = 1; hDevice < MAX_HANDLES; hDevice++) { if(HANDLE_OPEN(hDevice) && GET_HANDLE(hDevice).device == dev) { // Remove the device link from the handle but leave the handle around dev->handles--; GET_HANDLE(hDevice).device = NULL; } } } unlock_mutex(&handle_list.mutex); // Free all controls of this device clear_control_list(dev); if(dev->device.shortName) free(dev->device.shortName); if(dev->device.name && dev->device.name != dev->v4l2_name) free(dev->device.name); if(dev->device.driver) free(dev->device.driver); if(dev->device.location && dev->device.location != dev->v4l2_name) free(dev->device.location); free(dev); } /** * Mark all entries in the device list as invalid. This allows the cleanup_device_list() * function to be used to clear the entire device list. * * Note: The device list should be locked before calling this function. */ static void invalidate_device_list (void) { Device *elem = device_list.first; while(elem) { elem->valid = 0; elem = elem->next; } } /** * Remove all entries marked as invalid from the device list. * * Note: The device list should be locked before calling this function. */ static void cleanup_device_list (void) { Device *elem = device_list.first; Device *prev = NULL, *next; while(elem) { next = elem->next; if(!elem->valid) { if(prev) prev->next = next; else device_list.first = next; delete_device(elem); device_list.count--; } else { prev = elem; } elem = next; } } /** * Searches the device list for the device with the given name. */ static Device *find_device_by_name (const char *name) { Device *elem = device_list.first; while(elem) { if(strcmp(name, elem->v4l2_name) == 0) return elem; elem = elem->next; } return NULL; } /** * Returns the length required to store all the (null-terminated) strings of the * given device in a buffer. */ static int get_device_dynamics_length (CDevice *device) { return strlen(device->shortName) + 1 + strlen(device->name) + 1 + strlen(device->driver) + 1 + strlen(device->location) + 1; } /** * Returns the length required to store all the (null-terminated) strings of the * current devices in a buffer. * * Note: The device list should be locked before calling this function. */ static int get_devices_dynamics_length (void) { int size = 0; Device *elem = device_list.first; while(elem) { size += get_device_dynamics_length(&elem->device); elem = elem->next; } return size; } /** * Synchronizes the device list with the information available in sysfs. */ static CResult refresh_device_list (void) { CResult ret = C_SUCCESS; DIR *v4l_dir = NULL; struct dirent *dir_entry; if(lock_mutex(&device_list.mutex)) return C_SYNC_ERROR; // Invalidate all list entries invalidate_device_list(); // Go through all devices in sysfs and validate the list entries that have // correspondences in sysfs. v4l_dir = opendir("/sys/class/video4linux"); if(v4l_dir) { while((dir_entry = readdir(v4l_dir))) { // Ignore non-video devices if(strstr(dir_entry->d_name, "video") != dir_entry->d_name && strstr(dir_entry->d_name, "subdev") != dir_entry->d_name) continue; Device *dev = find_device_by_name(dir_entry->d_name); if(dev) { dev->valid = 1; } else { dev = create_device(dir_entry->d_name); if(dev == NULL) { ret = C_NO_MEMORY; goto done; } // Read detail information about the device ret = refresh_device_details(dev); if(ret) { // Invalidate the device immediately, so it gets deleted by the call // to cleanup_device_list() below. dev->valid = 0; // If there was a V4L2 error reset the error code, so that device enumeration // continues. This is necessary because V4L1 devices will let // refresh_device_details fail as they don't understand VIDIOC_QUERYCAP. if(ret == C_V4L2_ERROR) { print_libwebcam_error( "Warning: The driver behind device %s does not seem to support V4L2.", dev->v4l2_name); ret = C_SUCCESS; continue; } break; } get_device_usb_info(dev, &dev->device.usb); // Create the control list for the given device ret = refresh_control_list(dev); if(ret) goto done; } } } // Clean out all invalid device list entries cleanup_device_list(); done: if(v4l_dir) closedir(v4l_dir); unlock_mutex(&device_list.mutex); if(ret) print_libwebcam_c_error(ret, "Unable to refresh device list."); return ret; } /** * Open the V4L2 device node with the given name. * * @param device_name A device name as accepted by c_open_device() * * @return * - 0 if the device could not be opened * - a device handle > 0 on success */ int open_v4l2_device(char *device_name) { int v4l2_dev; char *dev_node; if(device_name == NULL) return C_INVALID_ARG; dev_node = (char *)malloc(5 + strlen(device_name) + 1); if(!dev_node) return 0; sprintf(dev_node, "/dev/%s", device_name); v4l2_dev = open(dev_node, 0); free(dev_node); return v4l2_dev; } /** * Retrieves the value of a given V4L2 control. */ static CResult read_v4l2_control(Device *device, Control *control, CControlValue *value, CHandle hDevice) { CResult ret = C_SUCCESS; if(device == NULL || control == NULL || value == NULL) return C_INVALID_ARG; int v4l2_dev = open_v4l2_device(device->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; #ifdef ENABLE_RAW_CONTROLS if(control->control.type == CC_TYPE_RAW) { unsigned int ctrl_size = control->control.max.raw.size; if(value->raw.data == NULL) return C_INVALID_ARG; if(value->raw.size < ctrl_size) return C_INVALID_ARG; struct v4l2_ext_control v4l2_ext_ctrl = { .id = control->v4l2_control, .size = ctrl_size, }; v4l2_ext_ctrl.string = value->raw.data; struct v4l2_ext_controls v4l2_ext_ctrls = { .ctrl_class = V4L2_CTRL_CLASS_USER, .count = 1, .controls = &v4l2_ext_ctrl }; if(ioctl(v4l2_dev, VIDIOC_G_EXT_CTRLS, &v4l2_ext_ctrls)) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } // Set the raw data size to the size of the control value->raw.size = ctrl_size; } else #endif { struct v4l2_control v4l2_ctrl = { .id = control->v4l2_control }; if(ioctl(v4l2_dev, VIDIOC_G_CTRL, &v4l2_ctrl)) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } value->value = v4l2_ctrl.value; } value->type = control->control.type; done: close(v4l2_dev); return ret; } /** * Changes the value of a given V4L2 control. */ static CResult write_v4l2_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice) { CResult ret = C_SUCCESS; if(device == NULL || control == NULL || value == NULL) return C_INVALID_ARG; int v4l2_dev = open_v4l2_device(device->v4l2_name); if(!v4l2_dev) return C_INVALID_DEVICE; #ifdef ENABLE_RAW_CONTROLS if(control->control.type == CC_TYPE_RAW) { unsigned int ctrl_size = control->control.max.raw.size; if(value->raw.data == NULL) return C_INVALID_ARG; if(value->raw.size < ctrl_size) return C_INVALID_ARG; struct v4l2_ext_control v4l2_ext_ctrl = { .id = control->v4l2_control, .size = ctrl_size, }; v4l2_ext_ctrl.string = value->raw.data; struct v4l2_ext_controls v4l2_ext_ctrls = { .ctrl_class = V4L2_CTRL_CLASS_USER, .count = 1, .controls = &v4l2_ext_ctrl }; if(ioctl(v4l2_dev, VIDIOC_S_EXT_CTRLS, &v4l2_ext_ctrls)) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); goto done; } } else #endif { struct v4l2_control v4l2_ctrl = { .id = control->v4l2_control, .value = value->value }; if(ioctl(v4l2_dev, VIDIOC_S_CTRL, &v4l2_ctrl)) { ret = C_V4L2_ERROR; set_last_error(hDevice, errno); } } #ifdef ENABLE_RAW_CONTROLS done: #endif close(v4l2_dev); return ret; } /** * Reads the USB information for the given device into the given #CUSBInfo structure. */ static CResult get_device_usb_info (Device *device, CUSBInfo *usbinfo) { if(device == NULL || usbinfo == NULL) return C_INVALID_ARG; // File names in the /sys/class/video4linux/video?/device directory and // corresponding pointers in the CUSBInfo structure. char *files[] = { "idVendor", "idProduct", "bcdDevice" }; unsigned short *fields[] = { &usbinfo->vendor, &usbinfo->product, &usbinfo->release }; // Read USB information int i; for(i = 0; i < 3; i++) { char *filename = NULL; if(asprintf(&filename, "/sys/class/video4linux/%s/device/../%s", device->v4l2_name, files[i]) < 0) return C_NO_MEMORY; FILE *input = fopen(filename, "r"); if(input) { if(fscanf(input, "%hx", fields[i]) != 1) *fields[i] = 0; fclose(input); } free(filename); } return C_SUCCESS; } /* * Utility functions */ /** * Converts a FourCC code into a MIME type string. */ static CResult get_mimetype_from_fourcc(char **mimetype, unsigned int fourcc) { if(mimetype == NULL) return C_INVALID_ARG; char *result; switch(fourcc) { case MAKE_FOURCC('Y','U','Y','2'): case MAKE_FOURCC('Y','U','Y','V'): result = "video/x-raw-yuv"; break; case MAKE_FOURCC('M','J','P','G'): result = "image/jpeg"; break; default: return C_NOT_FOUND; }; *mimetype = strdup(result); return C_SUCCESS; } /* * Handle management */ /** * Creates a new device handle for the given device. * * @return * - 0 if there are no free handles left. * - A libwebcam handle > 0 on success. */ static CHandle create_handle(Device *device) { CHandle handle = handle_list.first_free; int first_free, next_free; if(device == NULL) return 0; if(handle == 0) { print_libwebcam_error("No free device handles left. Unable to create handle " "for device '%s'.", device->v4l2_name); return 0; } if(lock_mutex(&handle_list.mutex)) return C_SYNC_ERROR; GET_HANDLE(handle).device = device; GET_HANDLE(handle).open = 1; device->handles++; // Look for the next free handle index first_free = handle_list.first_free; next_free = first_free; do { next_free = (next_free + 1) % MAX_HANDLES; if(next_free == 0) next_free = 1; if(!HANDLE_OPEN(next_free)) { handle_list.first_free = next_free; break; } } while(next_free != first_free); if(next_free == first_free) handle_list.first_free = 0; // No free handles left unlock_mutex(&handle_list.mutex); return handle; } /** * Closes the given handle. */ static void close_handle(CHandle hDevice) { if(!HANDLE_OPEN(hDevice)) return; // If the handle is open, close it. If it is also valid, remove the device reference. if(HANDLE_VALID(hDevice)) { lock_mutex(&handle_list.mutex); GET_HANDLE(hDevice).device->handles--; GET_HANDLE(hDevice).device = NULL; GET_HANDLE(hDevice).open = 0; unlock_mutex(&handle_list.mutex); } else { GET_HANDLE(hDevice).open = 0; } GET_HANDLE(hDevice).last_system_error = 0; } /** * Sets the last system error for the given handle. */ void set_last_error(CHandle hDevice, int error) { if(HANDLE_OPEN(hDevice)) GET_HANDLE(hDevice).last_system_error = error; } /* * Initialization and cleanup */ /** * Initializes libwebcam. * This method must be called prior to using most of the other methods. * To release resources allocated during initialization, users should make a call * to c_cleanup() when the library is no longer used. */ CResult c_init(void) { CResult ret = C_SUCCESS; // Don't reinitialize if(initialized) return C_SUCCESS; // Initialize the handle list memset(&handle_list, 0, sizeof(handle_list)); handle_list.first_free = 1; if(pthread_mutex_init(&handle_list.mutex, NULL)) return C_INIT_ERROR; // Initialize the device list device_list.first = NULL; if(pthread_mutex_init(&device_list.mutex, NULL)) return C_INIT_ERROR; device_list.count = 0; ret = refresh_device_list(); if(ret == C_SUCCESS) initialized = 1; return ret; } /** * Clean up resources. * This method should be called when the library is no longer used. */ void c_cleanup(void) { if(!initialized) return; initialized = 0; // Clear the device list lock_mutex(&device_list.mutex); invalidate_device_list(); cleanup_device_list(); unlock_mutex(&device_list.mutex); pthread_mutex_destroy(&device_list.mutex); pthread_mutex_destroy(&handle_list.mutex); } /** * Make sure the library resources are cleaned up when the library is unloaded. */ static void __attribute__ ((constructor)) c_unload(void) { c_cleanup(); } libwebcam-src-0.2.4/libwebcam/compat.h0000755000175000017500000001310312234547770016646 0ustar paulopaulo/** * \file * Declarations for compatibility with different V4L2 versions. * * \ingroup libwebcam */ /* * Copyright (c) 2006-2009 Logitech. * * This file is part of libwebcam. * * libwebcam is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libwebcam 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libwebcam. If not, see . */ #ifndef C_COMPAT_H #define C_COMPAT_H #include #ifdef USE_UVCVIDEO #define __user #include #endif #ifndef UVC_CONTROL_SET_CUR /* Control flags */ #define UVC_CONTROL_SET_CUR (1 << 0) #define UVC_CONTROL_GET_CUR (1 << 1) #define UVC_CONTROL_GET_MIN (1 << 2) #define UVC_CONTROL_GET_MAX (1 << 3) #define UVC_CONTROL_GET_RES (1 << 4) #define UVC_CONTROL_GET_DEF (1 << 5) /* Control should be saved at suspend and restored at resume. */ #define UVC_CONTROL_RESTORE (1 << 6) /* Control can be updated by the camera. */ #define UVC_CONTROL_AUTO_UPDATE (1 << 7) #define UVC_CONTROL_GET_RANGE (UVC_CONTROL_GET_CUR | UVC_CONTROL_GET_MIN | \ UVC_CONTROL_GET_MAX | UVC_CONTROL_GET_RES | \ UVC_CONTROL_GET_DEF) #endif #ifndef UVCIOC_CTRL_ADD struct uvc_xu_control_info { __u8 entity[16]; __u8 index; __u8 selector; __u16 size; __u32 flags; }; #endif // uvcvideo.h // Old uvcvideo pre-r178 control IDs #define UVC_CID_BACKLIGHT_COMPENSATION (V4L2_CID_PRIVATE_BASE+0) #define UVC_CID_POWER_LINE_FREQUENCY (V4L2_CID_PRIVATE_BASE+1) #define UVC_CID_SHARPNESS (V4L2_CID_PRIVATE_BASE+2) #define UVC_CID_HUE_AUTO (V4L2_CID_PRIVATE_BASE+3) #define UVC_CID_FOCUS_AUTO (V4L2_CID_PRIVATE_BASE+4) #define UVC_CID_FOCUS_ABSOLUTE (V4L2_CID_PRIVATE_BASE+5) #define UVC_CID_FOCUS_RELATIVE (V4L2_CID_PRIVATE_BASE+6) #define UVC_CID_PAN_RELATIVE (V4L2_CID_PRIVATE_BASE+7) #define UVC_CID_TILT_RELATIVE (V4L2_CID_PRIVATE_BASE+8) #define UVC_CID_PANTILT_RESET (V4L2_CID_PRIVATE_BASE+9) #define UVC_CID_EXPOSURE_AUTO (V4L2_CID_PRIVATE_BASE+10) #define UVC_CID_EXPOSURE_ABSOLUTE (V4L2_CID_PRIVATE_BASE+11) #define UVC_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_PRIVATE_BASE+14) #define UVC_CID_WHITE_BALANCE_TEMPERATURE_AUTO (V4L2_CID_PRIVATE_BASE+12) #define UVC_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_PRIVATE_BASE+13) // videodev2.h // Class IDs #ifndef V4L2_CTRL_CLASS_USER #define V4L2_CTRL_CLASS_USER 0x00980000 #endif #ifndef V4L2_CTRL_CLASS_MPEG #define V4L2_CTRL_CLASS_MPEG 0x00990000 #endif #ifndef V4L2_CTRL_CLASS_CAMERA #define V4L2_CTRL_CLASS_CAMERA 0x009a0000 #endif // Macros #ifndef V4L2_CTRL_ID2CLASS #define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) #endif // User controls from newer V4L2 versions #ifndef V4L2_CID_POWER_LINE_FREQUENCY #define V4L2_CID_POWER_LINE_FREQUENCY (V4L2_CID_BASE+24) #endif #ifndef V4L2_CID_HUE_AUTO #define V4L2_CID_HUE_AUTO (V4L2_CID_BASE+25) #endif #ifndef V4L2_CID_WHITE_BALANCE_TEMPERATURE #define V4L2_CID_WHITE_BALANCE_TEMPERATURE (V4L2_CID_BASE+26) #endif #ifndef V4L2_CID_SHARPNESS #define V4L2_CID_SHARPNESS (V4L2_CID_BASE+27) #endif #ifndef V4L2_CID_BACKLIGHT_COMPENSATION #define V4L2_CID_BACKLIGHT_COMPENSATION (V4L2_CID_BASE+28) #endif // Camera class controls from newer V4L2 versions #ifndef V4L2_CID_CAMERA_CLASS_BASE #define V4L2_CID_CAMERA_CLASS_BASE (V4L2_CTRL_CLASS_CAMERA | 0x900) #endif #ifndef V4L2_CID_EXPOSURE_AUTO #define V4L2_CID_EXPOSURE_AUTO (V4L2_CID_CAMERA_CLASS_BASE+1) #endif #ifndef V4L2_CID_EXPOSURE_ABSOLUTE #define V4L2_CID_EXPOSURE_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+2) #endif #ifndef V4L2_CID_EXPOSURE_AUTO_PRIORITY #define V4L2_CID_EXPOSURE_AUTO_PRIORITY (V4L2_CID_CAMERA_CLASS_BASE+3) #endif #ifndef V4L2_CID_PAN_RELATIVE #define V4L2_CID_PAN_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+4) #endif #ifndef V4L2_CID_TILT_RELATIVE #define V4L2_CID_TILT_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+5) #endif #ifndef V4L2_CID_PAN_RESET #define V4L2_CID_PAN_RESET (V4L2_CID_CAMERA_CLASS_BASE+6) #endif #ifndef V4L2_CID_TILT_RESET #define V4L2_CID_TILT_RESET (V4L2_CID_CAMERA_CLASS_BASE+7) #endif #ifndef V4L2_CID_PAN_ABSOLUTE #define V4L2_CID_PAN_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+8) #endif #ifndef V4L2_CID_TILT_ABSOLUTE #define V4L2_CID_TILT_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+9) #endif #ifndef V4L2_CID_FOCUS_ABSOLUTE #define V4L2_CID_FOCUS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+10) #endif #ifndef V4L2_CID_FOCUS_RELATIVE #define V4L2_CID_FOCUS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+11) #endif #ifndef V4L2_CID_FOCUS_AUTO #define V4L2_CID_FOCUS_AUTO (V4L2_CID_CAMERA_CLASS_BASE+12) #endif #ifndef V4L2_CID_ZOOM_ABSOLUTE #define V4L2_CID_ZOOM_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+13) #endif #ifndef V4L2_CID_ZOOM_RELATIVE #define V4L2_CID_ZOOM_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+14) #endif #ifndef V4L2_CID_ZOOM_CONTINUOUS #define V4L2_CID_ZOOM_CONTINUOUS (V4L2_CID_CAMERA_CLASS_BASE+15) #endif #ifndef V4L2_CID_PRIVACY #define V4L2_CID_PRIVACY (V4L2_CID_CAMERA_CLASS_BASE+16) #endif #ifndef V4L2_CID_IRIS_ABSOLUTE #define V4L2_CID_IRIS_ABSOLUTE (V4L2_CID_CAMERA_CLASS_BASE+17) #endif #ifndef V4L2_CID_IRIS_RELATIVE #define V4L2_CID_IRIS_RELATIVE (V4L2_CID_CAMERA_CLASS_BASE+18) #endif #endif /* C_COMPAT_H */ libwebcam-src-0.2.4/libwebcam/README0000644000175000017500000001333012234547770016071 0ustar paulopaulolibwebcam Webcam Library ======================== Introduction ------------ The Webcam Library libwebcam is designed to simplify the development of webcam applications, primarily on Linux but with an option to be ported to other platforms, in particular Solaris. It realizes part of what the unwritten Video4Linux user space library was always supposed to be: an easy to use library that shields its users from many of the difficulties and problems of using the V4L2 API directly. Today libwebcam provides the following core features: * Enumeration of all cameras available in the system. * Provide detailed information about the detected devices and their controls. * Wrapper for the V4L2 frame format enumeration. * Convenient access to device controls. * Support for configuring the Linux UVC driver's dynamic controls (extension unit controls). In addition, the interface is prepared to handle device events ranging from newly detected cameras over control value changes to device button events. It is easy to add new features without breaking application compatibility and the addition of new controls or events is straightforward. Change log ---------- 0.2.0 (under development): - Reorganized the directory layout and build system (CMake 2.6 is required now). - Added packaging support (.deb and .tar.bz2). - Added support for raw/string controls. - Minor bugfixes and code cleanups 0.1.4-pre (unreleased, SVN tag only): Note: This is the last version to use the old directory layout and CMake 2.4. - Improved udev support (udev >= 141 is required now). 0.1.3-pre (unreleased, SVN tag only): Note: This is the last version to work with older versions of udev. - Added support for some Logitech specific dynamic controls: LED1 mode, LED1 frequency, Disable color processing, Raw bits per pixel - Added a check for driver misbehavior related to V4L2_CTRL_FLAG_NEXT_CTRL and avoid an endless control enumeration loop. - Disable the UVC driver's caching mechanism for XU controls. - Build system: Use the CMAKE_INSTALL_LIBDIR variable for the library installation path. This should fix problems on Fedora 64-bit. 0.1.2 (2009-07-08): - Update the controls to work better with the latest version of the UVC driver that is part of the kernel. - Improved control handling by adding a list of well-known controls. This allows libwebcam to recognize certain controls even if header files on the build system do not match the current system. - Better handling of unknown control IDs. - Improved warning/error messages related to controls. 0.1.1 (2008-01-29): - Added support the V4L2_CTRL_FLAG_READ_ONLY flag. - Added per handle tracking of the last system error and a new c_get_handle_error_text function that allows a handle's last system error to be retrieved in certain cases (C_V4L2_ERROR). - Added a test to check whether the driver supports dynamic controls or not. This should prevent some confusing error 22 messages when "uvcdynctrl -i" is used with an old driver. - Process meta information and constants only while parsing the XML document for the first time (during the first device). - Implemented support for processing statistics. - Added some informational messages, e.g. about skipped devices. - Added a define to suppress EEXIST errors for all but the first device. - Improved the way the device is picked. Instead of just taking the first device, all devices are now looped through and supported UVC devices get their controls and mappings added. This is not quite necessary at the moment because the UVC driver still has global controls but that may change in the future. - Added a stub implementation of c_add_control_mappings_from_file for when DISABLE_UVCVIDEO_DYNCTRL is set. - Added a workaround for the current UVC driver's problematic V4L2_CID_EXPOSURE_AUTO control. This is a menu control whose menu choices don't have contiguous IDs but { 1, 2, 4, 8 } instead. For the moment, the library just skips that control. - Improved detection of invalid menu controls whose full choice range is not correctly queriable. - Fix: Bogus warning messages related to the V4L2 control types 'Button' and 'Integer64'. Support for these types in libwebcam is still missing, though. - Fix: Device enumeration issue with V4L1 devices present in the system. - Fix: Reorganizations in the control enumeration code and inclusion of a workaround for some dangerous behavior in the bttv driver. (Thanks to Bruno Grasland for his bttv testing!) - Fix: Problem in c_enum_frame_intervals if a non-discrete frame size was passed. The function now returns C_INVALID_ARG in this case. - Fix: A segfault would occur in c_enum_pixel_formats with unknown pixel formats (i.e. pixel formats without hardcoded MIME type). - Fix: Disabling USE_UVCVIDEO now works again and also sets DISABLE_UVCVIDEO_DYNCTRL. This allows compiling libwebcam without the uvcvideo header files. 0.1: Initial release Building, questions, and feedback --------------------------------- Please see the README file in the top level directory for building instructions and how to contact the developers. Copyright and license --------------------- Copyright (c) 2006-2010 Logitech. libwebcam is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libwebcam 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with libwebcam. If not, see . libwebcam-src-0.2.4/libwebcam/libwebcam.h0000644000175000017500000002275212234547770017317 0ustar paulopaulo/** * \file * Webcam library declarations. * * \ingroup libwebcam */ /* * Copyright (c) 2006-2008 Logitech. * * This file is part of libwebcam. * * libwebcam is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libwebcam 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libwebcam. If not, see . */ #ifndef C_LIBWEBCAM_H #define C_LIBWEBCAM_H #include #include #include /* * Features */ /// Whether private controls of the Linux UVC driver should be used or not #define USE_UVCVIDEO #ifdef USE_UVCVIDEO /// Whether to compile in support functions for the Linux UVC driver's dynamic /// controls. #define ENABLE_UVCVIDEO_DYNCTRL #ifdef ENABLE_UVCVIDEO_DYNCTRL /// Whether to include the automatically generated Logitech dynamic controls /// header file. #define USE_LOGITECH_DYNCTRL /// Whether to include support for raw controls. /// Note that this requires V4L2_CTRL_TYPE_STRING to be available (i.e. V4L2 >= 2.6.32). /// This is disabled by default but CMake enables it if it finds V4L2_CTRL_TYPE_STRING. //#define ENABLE_RAW_CONTROLS #endif #endif /* * Constants */ /// Whether to use the V4L2_CTRL_FLAG_NEXT_CTRL flag when enumerating V4L2 controls #define ENABLE_V4L2_ADVANCED_CONTROL_ENUMERATION /// Ignore EEXIST errors for the UVCIOC_CTRL_ADD and UVCIOC_CTRL_MAP ioctls for /// all but the first device. This is required if the driver uses global controls /// instead of per-device controls. #define DYNCTRL_IGNORE_EEXIST_AFTER_PASS1 /// The maximum number (plus 1) of handles libwebcam supports #define MAX_HANDLES 32 /// Debug option to disable locking #define DISABLE_LOCKING 1 /// Debug option to add verbosity to locking and unlocking #define DEBUG_LOCKING 1 /// The name used for controls whose name could not be retrieved. #define UNKNOWN_CONTROL_NAME "Unknown control" /// Number of retries for failed V4L2 ioctl requests. /// This is a workaround for faulty devices. #define CONTROL_IO_ERROR_RETRIES 2 /// Size of a GUID in bytes #define GUID_SIZE 16 /* * Macros */ #define HAS_VERBOSE() (0) #define PRINT_PREFIX "[libwebcam] " /// Free a pointer only if it is non-NULL and set it to NULL afterwards #define SAFE_FREE(p) if(p) { free(p); (p) = NULL; } /// Returns the given handle structure #define GET_HANDLE(handle) (handle_list.handles[(handle)]) /// Returns true if the given handle is open (valid or invalid) #define HANDLE_OPEN(handle) ((handle) < MAX_HANDLES && GET_HANDLE(handle).open) /// Returns true if the given handle is open and valid #define HANDLE_VALID(handle) (HANDLE_OPEN(handle) && GET_HANDLE(handle).device) /// Returns the maximum number of characters that a menu-type control choice /// can have in V4L2. #define V4L2_MENU_CTRL_MAX_NAME_SIZE sizeof(((struct v4l2_querymenu *)NULL)->name) /// Converts the given characters into a FourCC code #define MAKE_FOURCC(c1,c2,c3,c4) \ (unsigned int)((long)c1 | (long)c2 << 8 | (long)c3 << 16 | (long)c4 << 24) /// Format string to print a GUID byte array with printf #define GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" /// Argument macro to print a GUID byte array with printf #define GUID_ARGS(guid) \ (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ (guid)[5], (guid)[4], \ (guid)[7], (guid)[6], \ (guid)[8], (guid)[9], \ (guid)[10], (guid)[11], (guid)[12], \ (guid)[13], (guid)[14], (guid)[15] /* * Structures */ /** * An internal control description associated with a device. */ typedef struct _Control { /// Control description CControl control; /// V4L2 ioctl mapping (non-0 for V4L2 controls) int v4l2_control; /// UVC Unit ID of the UVC extension unit to which the control belongs unsigned char uvc_unitid; /// Control selector of the UVC extension unit control unsigned char uvc_selector; /// Size of the UVC extension unit control (non-0 for UVC controls) uint16_t uvc_size; /// Pointer to the next control in the list struct _Control * next; } Control; /** * Base structure that contains a list of controls and associated data. */ typedef struct _ControlList { /// The first control in the list Control * first; /// The last control in the list Control * last; /// The mutex used to serialize access to the control list pthread_mutex_t mutex; /// The number of controls contained in the list int count; } ControlList; /** * Internal device information. */ typedef struct _Device { /// Device information CDevice device; /// Short V4L2 device name (e.g. 'video0') char v4l2_name[NAME_MAX]; /// Short media device name (e.g. 'media0') char media_name[NAME_MAX]; /// Number of handles associated with this device int handles; /// List of controls supported by this device ControlList controls; /// Boolean whether the device is still valid, i.e. exists in the system. /// Devices marked as invalid will be cleared out by cleanup_device_list(). int valid; /// Version of the driver behind the device (formatted using KERNEL_VERSION) uint32_t driver_version; /// Next device in the global device list struct _Device * next; } Device; /** * Base structure that contains a list of devices and associated data. */ typedef struct _DeviceList { /// The first device in the list Device * first; /// The mutex used to serialize access to the device list pthread_mutex_t mutex; /// The number of devices contained in the list int count; } DeviceList; /** * Information associated with a device handle. * * Note that a handle can have three different states: * - Closed/free: The device handle is not being used by an application. * - Valid: The device handle is open by an application and points to a valid device. * - Invalid: The device handle is open by an application but does not point to a * (valid) device anymore. This happens when a device is removed from the system * but there are still open handles around. * An "open" handle can be both valid or invalid. */ typedef struct _Handle { /// Pointer to the device structure associated with this handle Device * device; /// True if the handle is open (valid or invalid) int open; /// The number of the last system error (e.g. a V4L2 return value) int last_system_error; } Handle; /** * Base structure that contains an array of device handles and associated data. */ typedef struct _HandleList { /// The array of handles Handle handles[MAX_HANDLES]; /// The mutex used to serialize access to the handle list pthread_mutex_t mutex; /// The index of the first free handle. /// Zero if there are now free handles at this time. int first_free; } HandleList; /* * Globals */ extern int initialized; extern HandleList handle_list; extern void print_error (char *format, ...); extern int open_v4l2_device(char *device_name); extern void set_last_error(CHandle hDevice, int error); extern CResult read_xu_control(Device *device, Control *control, CControlValue *value, CHandle hDevice); extern CResult write_xu_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice); extern CResult init_xu_control(Device *device, Control *control); /* * Helper functions */ /** * Acquire a mutex. * * This function is identical to pthread_mutex_lock except that it has different * return values and supports some debug flags. * * @return * C_SUCCESS if the mutex was successfully acquired * C_SYNC_ERROR if an error occured while trying to acquire the mutex */ static inline CResult lock_mutex (pthread_mutex_t *mutex) { #ifndef DISABLE_LOCKING #ifdef DEBUG_LOCKING fprintf(stderr, "Acquiring mutex 0x%08x ...\n", (unsigned int)mutex); #endif int ret = pthread_mutex_lock(mutex); #ifdef DEBUG_LOCKING fprintf(stderr, "Acquisition of mutex 0x%08x %s.\n", (unsigned int)mutex, ret ? "failed" : "successful"); #endif assert(ret == 0); return ret ? C_SYNC_ERROR : C_SUCCESS; #else return C_SUCCESS; #endif } /** * Release a mutex. * * This function is identical to pthread_mutex_unlock except that it has different * return values and supports some debug flags. * * @return * C_SUCCESS if the mutex was successfully released * C_SYNC_ERROR if an error occured while trying to release the mutex */ static inline void unlock_mutex (pthread_mutex_t *mutex) { #ifndef DISABLE_LOCKING #ifdef DEBUG_LOCKING fprintf(stderr, "Releasing mutex 0x%08x ...\n", (unsigned int)mutex); #endif int ret = pthread_mutex_unlock(mutex); #ifdef DEBUG_LOCKING fprintf(stderr, "Release of mutex 0x%08x %s.\n", (unsigned int)mutex, ret ? "failed" : "successful"); #endif assert(ret == 0); #endif } /** * Copies a variable-length string to the part of an enumeration buffer that is * reserved for dynamic data. * * This function is used by the enumeration functions. */ static inline void copy_string_to_buffer (char **target, char *source, void *buffer, unsigned int *offset) { unsigned int length = strlen(source); *target = (char *)buffer + *offset; memcpy(*target, source, length + 1); *offset += length + 1; } #endif /* C_LIBWEBCAM_H */ libwebcam-src-0.2.4/libwebcam/dynctrl.c0000644000175000017500000020313412234547770017037 0ustar paulopaulo/** * \file * Dynamic control support for the Linux UVC driver. * * \ingroup libwebcam */ /* * Copyright (c) 2006-2009 Logitech. * * This file is part of libwebcam. * * libwebcam is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libwebcam 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libwebcam. If not, see . */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include "webcam.h" #include "libwebcam.h" #ifdef ENABLE_UVCVIDEO_DYNCTRL #include "compat.h" #include #include /* * Macros */ /// get the number of elemts from the array #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /// Zero out a variable #define ZERO_STRUCT(s) memset(&(s), 0, sizeof(s)) /// Macro to silence unused variable warnings #define UNUSED_PARAMETER(x) (void)x; /// Convert a single hex character into its numeric value #define HEX_DECODE_CHAR(c) ((c) >= '0' && (c) <= '9' ? (c) - '0' : (tolower(c)) - 'a' + 0xA) /// Convert two hex characters into their byte value #define HEX_DECODE_BYTE(cc) ((HEX_DECODE_CHAR((cc)[0]) << 4) + HEX_DECODE_CHAR((cc)[1])) /// Helper macro to convert the UTF-8 strings used by libxml2 into ASCII #define UNICODE_TO_ASCII(s) (unicode_to_ascii(s, ctx)) /// Helper macro to convert the UTF-8 strings used by libxml2 into whitespace normalized ASCII #define UNICODE_TO_NORM_ASCII(s) (unicode_to_normalized_ascii(s, ctx)) /// Format string to print a GUID byte array with printf #define GUID_FORMAT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x" /// Argument macro to print a GUID byte array with printf #define GUID_ARGS(guid) \ (guid)[3], (guid)[2], (guid)[1], (guid)[0], \ (guid)[5], (guid)[4], \ (guid)[7], (guid)[6], \ (guid)[8], (guid)[9], \ (guid)[10], (guid)[11], (guid)[12], \ (guid)[13], (guid)[14], (guid)[15] /* * Enumerations */ /** * Type of constants that are allowed in the XML configuration file. */ typedef enum _ConstantType { CT_INVALID = 0, ///< Invalid type (used internally) CT_INTEGER, ///< Signed integer constant CT_GUID, ///< GUID } ConstantType; // Define uvc_control_data_type which existed for uvcvideo < r209. // It has been removed because enum's are not binary compatible on certain platforms among // different compilers. In our case we don't care and enums are handy, so we redefine it. #ifdef UVC_CTRL_DATA_TYPE_RAW #undef UVC_CTRL_DATA_TYPE_RAW #undef UVC_CTRL_DATA_TYPE_SIGNED #undef UVC_CTRL_DATA_TYPE_UNSIGNED #undef UVC_CTRL_DATA_TYPE_BOOLEAN #undef UVC_CTRL_DATA_TYPE_ENUM #undef UVC_CTRL_DATA_TYPE_BITMASK /** * Data type for dynamic UVC driver controls. */ enum uvc_control_data_type { UVC_CTRL_DATA_TYPE_RAW = 0, UVC_CTRL_DATA_TYPE_SIGNED, UVC_CTRL_DATA_TYPE_UNSIGNED, UVC_CTRL_DATA_TYPE_BOOLEAN, UVC_CTRL_DATA_TYPE_ENUM, UVC_CTRL_DATA_TYPE_BITMASK, }; #endif /* * Types */ /** * Constant read from the XML configuration file. */ typedef struct _Constant { /// Data type of the constant ConstantType type; /// Name of the constant char * name; union { /// Integer value (only valid if type == CT_INTEGER) int value; /// GUID value (only valid if type == CT_GUID) __u8 guid[GUID_SIZE]; }; /// Pointer to the next constant in the list struct _Constant * next; } Constant; /** * UVC extension unit control for use with UVCIOC_CTRL_ADD. */ typedef struct _UVCXUControl { /// Unique identifier of the extension unit control definition xmlChar * id; /// UVC data required to identify an extension unit control struct uvc_xu_control_info info; /// Pointer to the next extension unit control definition in the list struct _UVCXUControl * next; /// Does the match section of this control match the current device int match; } UVCXUControl; /** * Helper structure that contains handles and information useful during the XML parsing process. */ typedef struct _ParseContext { /// Structure used to pass information between the application and libwebcam. Can be NULL. CDynctrlInfo * info; /// XML document tree representing a dynamic controls configuration xmlDoc * xml_doc; /// Size of the info->messages buffer (which contains the CDynctrlMessage structures /// and the strings pointed to). unsigned int messages_size; /// Conversion descriptor for iconv iconv_t cd; /// List of constants parsed from the @c constants node Constant * constants; /// Device info CDevice * device; /// Handle to the libwebcam device CHandle handle; /// Handle to the V4L2 device that is used to add the dynamic controls int v4l2_handle; /// List of controls parsed from the @c devices nodes UVCXUControl * controls; /// The current parsing pass (first device is pass 1, second device pass 2, etc.) int pass; } ParseContext; /* * Helper functions */ /** * Converts a GUID string into a GUID byte array. * * This function assumes that @a guid is a valid GUID string. No validation is performed. */ static void guid_to_byte_array (const char *guid, __u8 *array) { array[ 0] = HEX_DECODE_BYTE(guid + 6); array[ 1] = HEX_DECODE_BYTE(guid + 4); array[ 2] = HEX_DECODE_BYTE(guid + 2); array[ 3] = HEX_DECODE_BYTE(guid ); array[ 4] = HEX_DECODE_BYTE(guid + 11); array[ 5] = HEX_DECODE_BYTE(guid + 9); array[ 6] = HEX_DECODE_BYTE(guid + 16); array[ 7] = HEX_DECODE_BYTE(guid + 14); array[ 8] = HEX_DECODE_BYTE(guid + 19); array[ 9] = HEX_DECODE_BYTE(guid + 21); array[10] = HEX_DECODE_BYTE(guid + 24); array[11] = HEX_DECODE_BYTE(guid + 26); array[12] = HEX_DECODE_BYTE(guid + 28); array[13] = HEX_DECODE_BYTE(guid + 30); array[14] = HEX_DECODE_BYTE(guid + 32); array[15] = HEX_DECODE_BYTE(guid + 34); } /** * 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. * * @param string String containing an integer. Can be NULL. * @param value A pointer in which the converted value will be stored. * Can be NULL if conversion is not required. * * @return boolean indicating whether the string represents a valid integer */ static int is_valid_integer_string (const char *string, int *value) { if(!string) return 0; char *end = NULL; int ret = strtol(string, &end, 0); if(*string != '\0' && *end == '\0') { if(value) *value = ret; return 1; } return 0; } /** * 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. * * @param value value to be checked * @param max upper threshold for the validity of @a value. If the threshold * is negative, no threshold check is performed, i.e. max == INT_MAX * is assumed. * * @return boolean indicating whether the value is a valid size */ static inline int is_valid_size (int value, int max) { return (value >= 0 && value <= (max < 0 ? INT_MAX : max)); } /** * 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. */ static int is_valid_size_string (const char *string, int *value, int max) { int temp_value = 0; if(is_valid_integer_string(string, &temp_value) && is_valid_size(temp_value, max)) { if(value) *value = temp_value; return 1; } return 0; } /** * Checks whether a given string represents a valid GUID. */ static int is_valid_guid (const char *string) { if(string == NULL && strlen(string) != 36) return 0; int i; for(i = 0; i < 36; i++) { switch(i) { case 8: case 13: case 18: case 23: if(string[i] != '-') return 0; break; default: if(!isxdigit(string[i])) return 0; } } return 1; } /** * 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. * * @param string version string to be converted * @param major pointer to an integer where the major version number should be stored * @param minor pointer to an integer where the minor version number should be stored * * @return boolean indicating whether the conversion succeeded or not */ static int string_to_version (const char *string, unsigned int *major, unsigned int *minor) { assert(string); unsigned int maj = 0, min = 0; // After the following conversion ... // if endptr == '.', we have a "x.y" format, // if endptr == '\0', we have a "x" format, // if endptr == string, there were no digits. char *end = NULL; maj = strtol(string, &end, 10); if(*end == '.') { min = atoi(end + 1); } if(major) *major = maj; if(minor) *minor = min; return end == string ? 0 : 1; } /** * Converts the name of a UVC request into its corresponding constant. * * @param name request string to be converted. Can be NULL. * * @return * - 0 if the conversion failed, i.e. the request name was not recognized * - a UVC_CONTROL_* constant if the conversion was successful */ //static __u32 get_uvc_request_by_name (const xmlChar *name) //{ // __u32 request = 0; // Used to denote an invalid/unsupported UVC control request // if(!name) return request; // // if(xmlStrEqual(name, BAD_CAST("SET_CUR"))) { // request = UVC_CONTROL_SET_CUR; // } // else if(xmlStrEqual(name, BAD_CAST("GET_CUR"))) { // request = UVC_CONTROL_GET_CUR; // } // else if(xmlStrEqual(name, BAD_CAST("GET_MIN"))) { // request = UVC_CONTROL_GET_MIN; // } // else if(xmlStrEqual(name, BAD_CAST("GET_MAX"))) { // request = UVC_CONTROL_GET_MAX; // } // else if(xmlStrEqual(name, BAD_CAST("GET_RES"))) { // request = UVC_CONTROL_GET_RES; // } // else if(xmlStrEqual(name, BAD_CAST("GET_DEF"))) { // request = UVC_CONTROL_GET_DEF; // } // return request; //} /** * Converts the name of a UVC data type constant into its corresponding numerical value. * * @param name data type string to be converted. Can be NULL. * * @return * - -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 */ static enum uvc_control_data_type get_uvc_ctrl_type_by_name (const xmlChar *name) { enum uvc_control_data_type type = -1; // Used to denote an invalid/unsupported UVC control type if(!name) return type; if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_RAW"))) { type = UVC_CTRL_DATA_TYPE_RAW; } else if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_SIGNED"))) { type = UVC_CTRL_DATA_TYPE_SIGNED; } else if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_UNSIGNED"))) { type = UVC_CTRL_DATA_TYPE_UNSIGNED; } else if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_BOOLEAN"))) { type = UVC_CTRL_DATA_TYPE_BOOLEAN; } else if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_ENUM"))) { type = UVC_CTRL_DATA_TYPE_ENUM; } else if(xmlStrEqual(name, BAD_CAST("UVC_CTRL_DATA_TYPE_BITMASK"))) { type = UVC_CTRL_DATA_TYPE_BITMASK; } return type; } /** * 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. * * @param name data type string to be converted. Can be NULL. * * @return * - 0 if the conversion failed, i.e. the data type name was not recognized * - a V4L2_CTRL_TYPE_* constant if the conversion was successful */ static enum v4l2_ctrl_type get_v4l2_ctrl_type_by_name (const xmlChar *name) { enum v4l2_ctrl_type type = 0; // Used to denote an invalid/unsupported V4L2 control type if(!name) return type; if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_INTEGER"))) { type = V4L2_CTRL_TYPE_INTEGER; } else if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_BOOLEAN"))) { type = V4L2_CTRL_TYPE_BOOLEAN; } else if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_BUTTON"))) { type = V4L2_CTRL_TYPE_BUTTON; } else if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_MENU"))) { type = V4L2_CTRL_TYPE_MENU; } #ifdef ENABLE_RAW_CONTROLS else if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_STRING"))) { type = V4L2_CTRL_TYPE_STRING; } #endif /* else if(xmlStrEqual(name, BAD_CAST("V4L2_CTRL_TYPE_INTEGER64"))) { type = V4L2_CTRL_TYPE_INTEGER64; } */ return type; } /** * 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. * * @param input input string to be normalized. This string is not modified. * * @return * - NULL if @a input is NULL or if memory could not be allocated * - a newly allocated buffer containing the output string */ static char *normalize_string (const char *input) { const char *whitespace = " \t\v\n\r\f"; if(!input) return NULL; // Skip whitespace at the beginning input += strspn(input, whitespace); // Allocate a new buffer for the normalized string unsigned int input_length = strlen(input) + 1; char *output = (char *)malloc(input_length); if(!output) return NULL; memset(output, 0, input_length); // Filter extra whitespace char *op = output; while(*input) { if(isspace(*input)) { while(*++input && isspace(*input)); if(!*input) break; *op++ = ' '; } *op++ = *input++; } return output; } /** * Converts a UTF-8 string to ASCII. * * The function may convert some characters in a non-reversible way. * * @param unicode input string to be converted. * @param ctx current parse context * * @return * - 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 */ static char *unicode_to_ascii (const xmlChar *unicode, ParseContext *ctx) { if(!unicode) return NULL; assert(ctx && ctx->cd && ctx->cd != (iconv_t)-1); // If there is no conversion descriptor return a copy of the input string if(!ctx || !ctx->cd || ctx->cd == (iconv_t)-1) return strdup((char *)unicode); // Allocate a new buffer as big as the input string char *inbuf, *outbuf, *ascii; size_t unicode_bytes, ascii_bytes; inbuf = (char *)unicode; ascii_bytes = unicode_bytes = strlen(inbuf) + 1; ascii = (char *)malloc(ascii_bytes); memset(ascii, 0, sizeof(*ascii)); outbuf = ascii; // Do the conversion if(iconv(ctx->cd, &inbuf, &unicode_bytes, &outbuf, &ascii_bytes) == -1) { assert(0); free(ascii); return NULL; } return ascii; } /** * 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. */ static char *unicode_to_normalized_ascii (const xmlChar *unicode, ParseContext *ctx) { char *ascii = unicode_to_ascii(unicode, ctx); char *normalized = normalize_string(ascii); free(ascii); return normalized; } /* * XML/libxml2 helper functions */ /** * Returns the text content of the given node. * * @param node Pointer to a node. May be NULL. * * @return * - 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 * */ static const xmlChar *xml_get_node_text (const xmlNode *node) { if(node && node->children && xmlNodeIsText(node->children)) { return node->children->content; } else { return NULL; } } /** * Returns the first child node with a given name. * * @param node pointer to the parent node whose children are to be searched * @param name the name of the child node to be searched for * * @return * - a pointer to the first child node with the given name * - NULL if no child node has the given name */ static xmlNode *xml_get_first_child_by_name (const xmlNode *node, const char *name) { xmlNode *cnode = node->children; while(cnode) { if(cnode->type == XML_ELEMENT_NODE && xmlStrEqual(cnode->name, BAD_CAST(name))) return cnode; cnode = cnode->next; } return NULL; } /** * Returns the next sibling node with a given name. * * @param node pointer to the node whose siblings are to be searched * @param name the name of the sibling node to be searched for * * @return * - a pointer to the first sibling node with the given name * - NULL if no sibling node has the given name */ static xmlNode *xml_get_next_sibling_by_name (const xmlNode *node, const char *name) { xmlNode *cnode = node->next; while(cnode) { if(cnode->type == XML_ELEMENT_NODE && xmlStrEqual(cnode->name, BAD_CAST(name))) return cnode; cnode = cnode->next; } return NULL; } /* * Data management and lookup functions */ /** * Look up a constant by its name. * * @param ctx current parse context * @param find_name name of the constant to look up * @param find_type only search for constants with this type. Specify CT_INVALID to * disable the type filter. * * @return * - NULL if no constant with the given name (and given type) could be found * - a pointer to the constant if the search was successful */ static Constant *lookup_constant (const char *find_name, ConstantType find_type, ParseContext *ctx) { Constant *elem = ctx->constants; while(elem) { if(strcmp(elem->name, find_name) == 0 && (find_type == CT_INVALID ? 1 : elem->type == find_type)) return elem; elem = elem->next; } return NULL; } /** * 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. * * @param text pointer to the name or integer value. Can be NULL. * @param value pointer to an integer to receive the converted or constant value * @param ctx current parse context * * @return * - 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 @a text is NULL, or if both conversion and lookup fail */ static CResult lookup_or_convert_to_integer (const xmlChar *text, int *value, ParseContext *ctx) { if(!text) return C_PARSE_ERROR; if(!is_valid_integer_string((const char *)text, value)) { Constant *constant = lookup_constant((const char *)text, CT_INTEGER, ctx); if(constant) { *value = constant->value; } else { return C_PARSE_ERROR; } } return C_SUCCESS; } /** * 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. */ static CResult lookup_or_convert_to_guid (const xmlChar *text, __u8 *guid, ParseContext *ctx) { if(!text) return C_PARSE_ERROR; if(is_valid_guid((const char *)text)) { guid_to_byte_array((const char *)text, guid); } else { Constant *constant = lookup_constant((const char *)text, CT_GUID, ctx); if(constant) { memcpy(guid, constant->guid, GUID_SIZE); } else { return C_PARSE_ERROR; } } return C_SUCCESS; } /** * Lookup a UVC extension unit control with the given name. */ static UVCXUControl * lookup_control (const xmlChar *name, ParseContext *ctx) { UVCXUControl *elem = ctx->controls; while(elem) { if(xmlStrEqual(elem->id, name)) return elem; elem = elem->next; } return NULL; } /** * 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. * * @param ctx current parse context * @param msg pointer 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. * * @return * - C_NO_MEMORY if the buffer could not be enlarged for lack of memory * - C_SUCCESS otherwise */ static CResult resize_message_buffer (ParseContext *ctx, CDynctrlMessage *msg) { CDynctrlMessage *new_messages = NULL; // Enlarge the CDynctrlMessage buffer and zero out the newly allocated space unsigned int extra_required = sizeof(CDynctrlMessage) + strlen(msg->text) + 1; new_messages = (CDynctrlMessage *)realloc(ctx->info->messages, ctx->messages_size + extra_required); if(new_messages == NULL) return C_NO_MEMORY; memset((unsigned char *)new_messages + ctx->messages_size, 0, extra_required); ctx->messages_size += extra_required; // Move the dynamics area (e.g. all strings) down (imagine ctx->messages as the top) // by sizeof(CDynctrlMessage) to make room for the new array element. // Note that to access the current .text string we already need to refer to the new // buffer (to the old location in the new buffer to be more specific) because the buffer // has been freed above. int i, dynamics_length = 0; for(i = 0; i < ctx->info->message_count; i++) { char *old_text = (char *)new_messages + ctx->info->message_count * sizeof(CDynctrlMessage) + dynamics_length; dynamics_length += strlen(old_text) + 1; // Note that the .text pointers will be invalid until we actually move the data below new_messages[i].text = old_text + sizeof(CDynctrlMessage); } if(i > 0) { memmove((unsigned char *)new_messages + (ctx->info->message_count + 1) * sizeof(CDynctrlMessage), (unsigned char *)new_messages + ctx->info->message_count * sizeof(CDynctrlMessage), dynamics_length); } // Copy the string of the new message to the end of the dynamics area char *new_text = (char *)((unsigned char *)new_messages + (ctx->info->message_count + 1) * sizeof(CDynctrlMessage) + dynamics_length); strcpy(new_text, msg->text); msg->text = new_text; // Update the message to point to the new text // Copy the new message to the end of the array and update the array size ctx->info->message_count++; memcpy(&new_messages[ctx->info->message_count - 1], msg, sizeof(CDynctrlMessage)); // Finally, update the context to point to the resized messages buffer ctx->info->messages = new_messages; return C_SUCCESS; } /** * Adds a new message to the message list. * * This function works like add_message() but takes a @a va_list argument instead * of a parameter list. */ static CResult add_message_v (ParseContext *ctx, int line, int col, CDynctrlMessageSeverity severity, const char *format, va_list va) { CResult ret = C_SUCCESS; if(!ctx->info) return C_INVALID_ARG; if(!(ctx->info->flags & CD_REPORT_ERRORS)) return C_SUCCESS; // Allocate a temporary buffer that contains the final message string char *text = NULL; int written = vasprintf(&text, format, va); if(written == -1) { ret = C_NO_MEMORY; goto done; } // Allocate memory for the new message (i.e. CDynctrlMessage and its string) CDynctrlMessage message = { 0 }; message.line = line; message.col = col; message.severity = severity; message.text = text; ret = resize_message_buffer(ctx, &message); if(ret) { ret = C_NO_MEMORY; goto done; } done: if(text) free(text); return ret; } /** * Adds a new message to the message list. * * @param ctx current parse context * @param line line number that the message concerns (e.g. line of the syntax error) * @param col column number that the message concerns * @param severity severity level of the message (warning, error, etc.) * @param format a printf compatible format to print the variable parameter list */ static CResult add_message (ParseContext *ctx, int line, int col, CDynctrlMessageSeverity severity, const char *format, ...) { va_list va; va_start(va, format); CResult ret = add_message_v(ctx, line, col, severity, format, va); va_end(va); return ret; } /** * Adds a new informational message to the message list. */ static CResult add_info (ParseContext *ctx, const char *format, ...) { va_list va; va_start(va, format); CResult ret = add_message_v(ctx, 0, 0, CD_SEVERITY_INFO, format, va); va_end(va); return ret; } /* static CResult add_warning (ParseContext *ctx, const char *format, ...) { va_list va; va_start(va, format); CResult ret = add_message_v(ctx, 0, 0, CD_SEVERITY_WARNING, format, va); va_end(va); return ret; } */ /** * Adds a new error message to the message list. */ static CResult add_error (ParseContext *ctx, const char *format, ...) { va_list va; va_start(va, format); CResult ret = add_message_v(ctx, 0, 0, CD_SEVERITY_ERROR, format, va); va_end(va); return ret; } /** * Adds a new error message concerning a given xmlNode to the message list. * * The node is used to extract the line number. */ static CResult add_error_at_node (ParseContext *ctx, const xmlNode *node, const char *format, ...) { assert(node); va_list va; va_start(va, format); CResult ret = add_message_v(ctx, node->line, 0, CD_SEVERITY_ERROR, format, va); va_end(va); return ret; } /* * Parsing functions */ /** * Parse a dynamic controls configuration XML file and return an XML document tree. * * @param file_name name (with an optional path) of the file to be parsed * @param ctx current parse context * * @return * - 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 */ static CResult parse_dynctrl_file (const char *file_name, ParseContext *ctx) { CResult ret = C_SUCCESS; xmlParserCtxt *parser = NULL; parser = xmlNewParserCtxt(); if(!parser) return C_NO_MEMORY; // Read and parse the XML file ctx->xml_doc = xmlCtxtReadFile(parser, file_name, NULL, XML_PARSE_NOBLANKS); if(!ctx->xml_doc) { xmlError *e = &parser->lastError; add_message(ctx, e->line, e->int2, CD_SEVERITY_ERROR, "Malformed control mapping file encountered. Unable to parse: %s", e->message); ret = C_PARSE_ERROR; } assert(parser->valid); #if 0 // TODO implement // Validate the XML file against the schema if(!ctx->info || !(ctx->info->flags & CD_DONT_VALIDATE)) { } // Free the document tree if there was an error if(ret) { xmlFreeDoc(ctx->doc); ctx->doc = NULL; } #endif // Clean up xmlFreeParserCtxt(parser); return ret; } /** * Process a @c mapping node and add the contained mapping to the UVC driver. */ static CResult process_mapping (const xmlNode *node_mapping, ParseContext *ctx) { CResult ret; assert(node_mapping); struct uvc_xu_control_mapping mapping_info = { 0 }; // At the moment only V4L2 mappings are supported xmlNode *node_v4l2 = xml_get_first_child_by_name(node_mapping, "v4l2"); if(!node_v4l2) { // TODO implement return C_NOT_IMPLEMENTED; } // Search for the node containing UVC information xmlNode *node_uvc = xml_get_first_child_by_name(node_mapping, "uvc"); if(!node_uvc) { add_error_at_node(ctx, node_mapping, "Mapping does not have UVC information. is mandatory."); return C_PARSE_ERROR; } // Look up the referenced control definition and fill in the UVC fields of // the uvc_xu_control_mapping structure. xmlNode *node_control_ref = xml_get_first_child_by_name(node_uvc, "control_ref"); if(!node_control_ref) { add_error_at_node(ctx, node_uvc, "Control reference missing. is mandatory."); return C_PARSE_ERROR; } xmlChar *control_ref = xmlGetProp(node_control_ref, BAD_CAST("idref")); if(!control_ref) { add_error_at_node(ctx, node_control_ref, "Invalid control reference. 'idref' attribute referencing a is mandatory."); return C_PARSE_ERROR; } UVCXUControl *control = lookup_control(control_ref, ctx); if(!control) { add_error_at_node(ctx, node_control_ref, "Invalid control reference: control with ID '%s' could not be found.", (char *)control_ref); xmlFree(control_ref); return C_PARSE_ERROR; } xmlFree(control_ref); control_ref = NULL; if (!control->match) return C_SUCCESS; memcpy(mapping_info.entity, control->info.entity, GUID_SIZE); mapping_info.selector = control->info.selector; // Copy the descriptive name (truncate if it's too long for V4L2/uvcvideo) char *name = UNICODE_TO_NORM_ASCII(xml_get_node_text(xml_get_first_child_by_name(node_mapping, "name"))); if(!name) { add_error_at_node(ctx, node_mapping, "Control mapping has no name. is mandatory."); return C_PARSE_ERROR; } strncpy((char *)mapping_info.name, name, sizeof(mapping_info.name) - 1); mapping_info.name[sizeof(mapping_info.name) - 1] = '\0'; free(name); name = NULL; // Fill in the V4L2 fields of the uvc_xu_control_mapping structure int value = 0; const xmlChar *text = xml_get_node_text(xml_get_first_child_by_name(node_v4l2, "id")); ret = lookup_or_convert_to_integer(text, &value, ctx); if(ret) { add_error_at_node(ctx, node_v4l2, "V4L2 ID contains invalid number or references unknown constant: '%s'", text ? (char *)text : ""); return C_PARSE_ERROR; } mapping_info.id = (__u32)value; text = xml_get_node_text(xml_get_first_child_by_name(node_v4l2, "v4l2_type")); enum v4l2_ctrl_type v4l2_type = get_v4l2_ctrl_type_by_name(text); if(v4l2_type == 0) { add_error_at_node(ctx, node_v4l2, "Invalid V4L2 control type specified: '%s'", text ? (char *)text : ""); return C_PARSE_ERROR; } mapping_info.v4l2_type = v4l2_type; // Fill in the remaining UVC fields of the uvc_xu_control_mappings structure char *string = UNICODE_TO_ASCII(xml_get_node_text(xml_get_first_child_by_name(node_uvc, "size"))); if(!is_valid_size_string(string, &value, 0xFF)) { add_error_at_node(ctx, node_v4l2, "Invalid UVC control size specified: '%s'", string ? string : ""); return C_PARSE_ERROR; } mapping_info.size = value; free(string); string = UNICODE_TO_ASCII(xml_get_node_text(xml_get_first_child_by_name(node_uvc, "offset"))); if(!is_valid_size_string(string, &value, 0xFF)) { add_error_at_node(ctx, node_v4l2, "Invalid UVC control offset specified: '%s'", string ? string : ""); return C_PARSE_ERROR; } mapping_info.offset = value; free(string); text = xml_get_node_text(xml_get_first_child_by_name(node_uvc, "uvc_type")); enum uvc_control_data_type uvc_type = get_uvc_ctrl_type_by_name(xml_get_node_text(xml_get_first_child_by_name(node_uvc, "uvc_type"))); if(uvc_type == -1) { add_error_at_node(ctx, node_v4l2, "Invalid UVC control type specified: '%s'", text ? (char *)text : ""); return C_PARSE_ERROR; } mapping_info.data_type = uvc_type; if(v4l2_type == V4L2_CTRL_TYPE_MENU) { xmlNode *node_menu = xml_get_first_child_by_name(node_v4l2, "menu_entry"); if(!node_menu) { add_error_at_node(ctx, node_v4l2, " is mandatory for mappings with a v4l2_type of V4L2_CTRL_TYPE_MENU"); return C_PARSE_ERROR; } mapping_info.menu_count = 1; while ((node_menu = xml_get_next_sibling_by_name(node_menu, "menu_entry"))) mapping_info.menu_count++; mapping_info.menu_info = malloc(mapping_info.menu_count * sizeof(struct uvc_menu_info)); if(!mapping_info.menu_info) return C_NO_MEMORY; int i; node_menu = xml_get_first_child_by_name(node_v4l2, "menu_entry"); for (i = 0; i < mapping_info.menu_count; i++) { xmlChar *menu_name_uni = xmlGetProp(node_menu, BAD_CAST("name")); char *menu_name_asc = UNICODE_TO_NORM_ASCII(menu_name_uni); if(!menu_name_asc) { add_error_at_node(ctx, node_menu, "Invalid menu_entry. 'name' attribute is mandatory."); free(mapping_info.menu_info); return C_PARSE_ERROR; } xmlChar *menu_value = xmlGetProp(node_menu, BAD_CAST("value")); if(!menu_value) { add_error_at_node(ctx, node_menu, "Invalid menu_entry. 'value' attribute is mandatory."); xmlFree(menu_name_uni); free(menu_name_asc); free(mapping_info.menu_info); return C_PARSE_ERROR; } snprintf((char *)mapping_info.menu_info[i].name, sizeof(mapping_info.menu_info[i].name), "%s", menu_name_asc); ret = lookup_or_convert_to_integer(menu_value, (int *)&mapping_info.menu_info[i].value, ctx); if(ret) add_error_at_node(ctx, node_menu, " value contains invalid number or references unknown constant: '%s'", menu_value); xmlFree(menu_value); xmlFree(menu_name_uni); free(menu_name_asc); if(ret) { free(mapping_info.menu_info); return C_PARSE_ERROR; } node_menu = xml_get_next_sibling_by_name(node_menu, "menu_entry"); } } // Add the control to the UVC driver's control list /* printf( "uvc_xu_control_mapping = {\n" " id = 0x%08x,\n" " name = '%s',\n" " entity = {" GUID_FORMAT "},\n" " selector = %u,\n" " size = %u,\n" " offset = %u,\n" " v4l2_type = %u,\n" " data_type = %u\n" "}\n", mapping_info.id, mapping_info.name, GUID_ARGS(mapping_info.entity), mapping_info.selector, mapping_info.size, mapping_info.offset, mapping_info.v4l2_type, mapping_info.data_type ); */ int v4l2_ret = ioctl(ctx->v4l2_handle, UVCIOC_CTRL_MAP, &mapping_info); free(mapping_info.menu_info); if(v4l2_ret != 0 #ifdef DYNCTRL_IGNORE_EEXIST_AFTER_PASS1 && (ctx->pass == 1 || errno != EEXIST) #endif ) { add_error(ctx, "%s: unable to map '%s' control. ioctl(UVCIOC_CTRL_MAP) failed with return value %d (error %d: %s)", GET_HANDLE(ctx->handle).device->v4l2_name, mapping_info.name, v4l2_ret, errno, strerror(errno)); return C_V4L2_ERROR; } return C_SUCCESS; } /** * Process a @c mappings node. */ static CResult process_mappings (const xmlNode *node_mappings, ParseContext *ctx) { assert(node_mappings); // Process all nodes xmlNode *node_mapping = xml_get_first_child_by_name(node_mappings, "mapping"); while(node_mapping) { CResult ret = process_mapping(node_mapping, ctx); if(ctx->info) { if(ret) ctx->info->stats.mappings.successful++; else ctx->info->stats.mappings.failed++; } node_mapping = xml_get_next_sibling_by_name(node_mapping, "mapping"); } return C_SUCCESS; } /** * Process a @c control node by adding the contained control to the UVC driver. */ static CResult process_control (xmlNode *node_control, ParseContext *ctx, int match) { CResult ret = C_SUCCESS; assert(node_control); const xmlChar *text = NULL; int value = 0; // Allocate memory for the extension unit control definition UVCXUControl *xu_control = (UVCXUControl *)malloc(sizeof(UVCXUControl)); if(!xu_control) return C_NO_MEMORY; memset(xu_control, 0, sizeof *xu_control); // Set match xu_control->match = match; // Get the ID of the extension unit control definition xu_control->id = xmlGetProp(node_control, BAD_CAST("id")); if(!xu_control->id) { add_error_at_node(ctx, node_control, "Control has no ID. 'id' attribute is mandatory."); ret = C_PARSE_ERROR; goto done; } // Retrieve the entity and check whether it's a constant or a GUID text = xml_get_node_text(xml_get_first_child_by_name(node_control, "entity")); ret = lookup_or_convert_to_guid(text, xu_control->info.entity, ctx); if(ret) { add_error_at_node(ctx, node_control, "Control entity contains invalid GUID or references unknown constant: '%s'", text ? (char *)text : ""); goto done; } // Retrieve the selector and check whether it's a constant or a GUID text = xml_get_node_text(xml_get_first_child_by_name(node_control, "selector")); ret = lookup_or_convert_to_integer(text, &value, ctx); if(ret) { add_error_at_node(ctx, node_control, "Control selector contains invalid number or references unknown constant: '%s'", text ? (char *)text : ""); goto done; } xu_control->info.selector = (__u8)value; // Add the extension unit control definition to the internal list for later // reference by mappings. xu_control->next = ctx->controls; ctx->controls = xu_control; done: if(xu_control && xu_control != ctx->controls) { // Only free xu_control if it was not added if(xu_control->id) // to the list. free(xu_control->id); free(xu_control); } return ret; } /** * Process a @c controls node. */ static CResult process_controls (const xmlNode *node_controls, ParseContext *ctx, int match) { assert(node_controls); // Process all nodes xmlNode *node_control = xml_get_first_child_by_name(node_controls, "control"); while(node_control) { CResult ret = process_control(node_control, ctx, match); if(ctx->info) { if(ret) ctx->info->stats.controls.successful++; else ctx->info->stats.controls.failed++; } node_control = xml_get_next_sibling_by_name(node_control, "control"); } return C_SUCCESS; } /** * Process a @c device node. * * Note that the contained @c match sections are currently ignored. */ static CResult process_device (const xmlNode *node_device, ParseContext *ctx) { xmlNode *node_match; assert(node_device); int match = 1; /* An entry without match sections always matches */ // Process match for (node_match = xml_get_first_child_by_name(node_device, "match"); node_match != NULL; node_match = xml_get_next_sibling_by_name(node_match, "match")) { int vid, pid; match = 0; xmlNode *node = xml_get_first_child_by_name(node_match, "vendor_id"); if (node == NULL || !is_valid_integer_string((char *)xml_get_node_text(node), &vid)) { add_error_at_node(ctx, node_match, " is mandatory for match sections and must be a valid integer"); return C_PARSE_ERROR; } if (vid != ctx->device->usb.vendor) continue; match = 1; /* Sessions with no product_id match on vendor only */ for (node = xml_get_first_child_by_name(node_match, "product_id"); node != NULL; node = xml_get_next_sibling_by_name(node, "product_id")) { match = 0; if (!is_valid_integer_string((char *)xml_get_node_text(node), &pid)) { add_error_at_node(ctx, node_match, " must be a valid integer"); return C_PARSE_ERROR; } if (pid == ctx->device->usb.product) { match = 1; break; } } break; } // Process the node xmlNode *node_controls = xml_get_first_child_by_name(node_device, "controls"); if(node_controls) process_controls(node_controls, ctx, match); return C_SUCCESS; } /** * Process a @c devices node. */ static CResult process_devices (const xmlNode *node_devices, ParseContext *ctx) { assert(node_devices); // Process all nodes xmlNode *node_device = xml_get_first_child_by_name(node_devices, "device"); while(node_device) { process_device(node_device, ctx); node_device = xml_get_next_sibling_by_name(node_device, "device"); } return C_SUCCESS; } /** * Process a @c constant node by adding the contained constant to an internal list. */ static CResult process_constant (xmlNode *node_constant, ParseContext *ctx) { CResult ret = C_SUCCESS; xmlChar *type = NULL; assert(node_constant); // Allocate memory for the constant list element Constant *constant = (Constant *)malloc(sizeof(Constant)); if(!constant) return C_NO_MEMORY; memset(constant, 0, sizeof(*constant)); // Read and convert the name constant->name = UNICODE_TO_ASCII(xml_get_node_text(xml_get_first_child_by_name(node_constant, "id"))); if(!constant->name) { add_error_at_node(ctx, node_constant, "Constant has no name. is mandatory."); ret = C_PARSE_ERROR; goto done; } if(lookup_constant(constant->name, CT_INVALID, ctx)) { add_error_at_node(ctx, node_constant, "Constant '%s' has already been defined. Ignoring redefinition.", constant->name); ret = C_PARSE_ERROR; goto done; } // Read the type of the constant type = xmlGetProp(node_constant, BAD_CAST("type")); if(xmlStrEqual(type, BAD_CAST("integer"))) { constant->type = CT_INTEGER; } else if(xmlStrEqual(type, BAD_CAST("guid"))) { constant->type = CT_GUID; } // Read the value of the constant const xmlNode *node_value; const xmlChar *value = xml_get_node_text(node_value = xml_get_first_child_by_name(node_constant, "value")); switch(constant->type) { case CT_INTEGER: if(!is_valid_integer_string((char *)value, &constant->value)) { add_error_at_node(ctx, node_value, "Integer constant %s has invalid value '%s'.", constant->name, (char *)value); ret = C_PARSE_ERROR; goto done; } break; case CT_GUID: guid_to_byte_array((char *)value, constant->guid); break; default: add_error_at_node(ctx, node_constant, "Constant has unknown type '%s' (must be 'integer' or 'guid').", (char *)type); ret = C_PARSE_ERROR; goto done; break; } // Add the constant to the internal list for later reference constant->next = ctx->constants; ctx->constants = constant; done: // Clean up if(type) xmlFree(type); if(constant != ctx->constants) free(constant); return ret; } /** * Process a @c constants node. */ static CResult process_constants (const xmlNode *node_constants, ParseContext *ctx) { assert(node_constants); // Process all nodes xmlNode *node_constant = xml_get_first_child_by_name(node_constants, "constant"); while(node_constant) { CResult ret = process_constant(node_constant, ctx); if(ctx->info) { if(ret) ctx->info->stats.constants.successful++; else ctx->info->stats.constants.failed++; } node_constant = xml_get_next_sibling_by_name(node_constant, "constant"); } return C_SUCCESS; } /** * Process a @c meta node by filling in the corresponding info structure. */ static CResult process_meta (const xmlNode *node_meta, ParseContext *ctx) { assert(node_meta); // Extract meta information if required if(ctx->info && ctx->info->flags & CD_RETRIEVE_META_INFO) { // Copy the version and revision numbers string_to_version( (char *)xml_get_node_text(xml_get_first_child_by_name(node_meta, "version")), &ctx->info->meta.version.major, &ctx->info->meta.version.minor); string_to_version( (char *)xml_get_node_text(xml_get_first_child_by_name(node_meta, "revision")), &ctx->info->meta.revision.major, &ctx->info->meta.revision.minor); // Copy the strings for author (normalized), contact, and copyright ctx->info->meta.author = unicode_to_normalized_ascii( xml_get_node_text(xml_get_first_child_by_name(node_meta, "author")), ctx); ctx->info->meta.contact = unicode_to_ascii( xml_get_node_text(xml_get_first_child_by_name(node_meta, "contact")), ctx); ctx->info->meta.copyright = unicode_to_ascii( xml_get_node_text(xml_get_first_child_by_name(node_meta, "copyright")), ctx); } return C_SUCCESS; } /** * Process an XML document tree representing a dynamic controls configuration file. */ static CResult process_dynctrl_doc (ParseContext *ctx) { CResult ret = C_SUCCESS; xmlNode *node_root = xmlDocGetRootElement(ctx->xml_doc); assert(node_root); ctx->pass++; // We start at pass 1 ... // Some processing only needs to be done in the first pass if(ctx->pass == 1) { // Find and process the node ret = process_meta(xml_get_first_child_by_name(node_root, "meta"), ctx); if(ret) return ret; // Find the list (if it exists) ret = process_constants(xml_get_first_child_by_name(node_root, "constants"), ctx); if(ret) return ret; } // Process all lists xmlNode *node_devices = xml_get_first_child_by_name(node_root, "devices"); while(node_devices) { process_devices(node_devices, ctx); node_devices = xml_get_next_sibling_by_name(node_devices, "devices"); } // Process the node ret = process_mappings(xml_get_first_child_by_name(node_root, "mappings"), ctx); return ret; } /** * 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. * * @param ctx current parse context * * @return * - #C_SUCCESS if the driver supports dynamic controls * - #C_NOT_IMPLEMENTED if the driver does not support dynamic controls */ static CResult device_supports_dynctrl(ParseContext *ctx) { CResult ret = C_SUCCESS; #ifdef UVCIOC_CTRL_ADD struct uvc_xu_control_info xu_control = { .entity = /* UVC_GUID_UVC_PROCESSING */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01 }, .selector = /* PU_BRIGHTNESS_CONTROL */ 0x02, .index = 0, .size = 0, .flags = 0 }; assert(ctx->v4l2_handle); int v4l2_ret = ioctl(ctx->v4l2_handle, UVCIOC_CTRL_ADD, &xu_control); if(v4l2_ret == -1) { if(errno == EPERM) { /* User is not root (newer drivers require root permissions) */ ret = C_CANNOT_WRITE; } else if(errno == EEXIST) { /* Driver supports dynamic controls */ } else { /* Unexpected error: Assume not supported */ ret = C_NOT_IMPLEMENTED; } } else { /* Success: Assume not supported */ ret = C_NOT_IMPLEMENTED; } #else struct uvc_xu_control_mapping xu_control = { .id = V4L2_CID_BRIGHTNESS, .name = "Brightness", .entity = /* UVC_GUID_UVC_PROCESSING */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01 }, .selector = /* PU_BRIGHTNESS_CONTROL */ 0x02, .size = 0, .offset = 0, .v4l2_type = V4L2_CTRL_TYPE_INTEGER, .data_type = UVC_CTRL_DATA_TYPE_SIGNED, .menu_info = NULL, .menu_count = 0, .reserved = {0,0,0,0}, }; int v4l2_ret = ioctl(ctx->v4l2_handle, UVCIOC_CTRL_MAP, &xu_control); if(v4l2_ret == -1) { if(errno == EPERM) { /* User is not root (newer drivers require root permissions) */ ret = C_CANNOT_WRITE; } else if(errno == ENOENT) { /* Driver supports dynamic controls */ } else { printf("UVCIOC_CTRL_MAP returned errno(%i)\n", errno); /* Unexpected error: Assume not supported */ ret = C_NOT_IMPLEMENTED; } } else { /* Success: Assume not supported */ ret = C_NOT_IMPLEMENTED; } #endif return ret; } /** * Adds controls and control mappings contained in the given XML tree to the UVC driver. * * @param ctx current parse context * * @return * - #C_INVALID_DEVICE if no devices are available * - #C_CANNOT_WRITE if the user does not have permissions to add the mappings * - #C_SUCCESS if adding the controls and control mappings was successful */ static CResult add_control_mappings (ParseContext *ctx) { CResult ret = C_SUCCESS; assert(HANDLE_OPEN(ctx->handle)); assert(HANDLE_VALID(ctx->handle)); // Open the V4L2 device ctx->v4l2_handle = open_v4l2_device(GET_HANDLE(ctx->handle).device->v4l2_name); if(!ctx->v4l2_handle) { ret = C_INVALID_DEVICE; goto done; } // Check if the driver supports dynamic controls ret = device_supports_dynctrl(ctx); if(ret) goto done; // Process the contained control mappings ret = process_dynctrl_doc(ctx); done: if (ret != C_SUCCESS) { if(ret == C_NOT_IMPLEMENTED) { add_error(ctx, "device '%s' skipped because the driver '%s' behind it does not seem " "to support dynamic controls.", ctx->device->shortName, ctx->device->driver ); } else if(ret == C_CANNOT_WRITE) { add_error(ctx, "device '%s' skipped because you do not have the right permissions. " "Newer driver versions require root permissions.", ctx->device->shortName ); } else { char *error = c_get_handle_error_text(ctx->handle, ret); assert(error); add_error(ctx, "device '%s' was not processed successfully: %s. (Code: %d)", ctx->device->shortName, error, ret ); free(error); } } // Close the device handle if(ctx && ctx->v4l2_handle) { close(ctx->v4l2_handle); ctx->v4l2_handle = 0; } return ret; } /** * Cleans up all resources held by the passed in ctx * * @param ctx current parse context */ static void destroy_context (ParseContext *ctx) { if(!ctx) return; // Close the conversion descriptor if(ctx->cd && ctx->cd != (iconv_t)-1) iconv_close(ctx->cd); if(ctx->xml_doc) xmlFreeDoc(ctx->xml_doc); // Free the ParseContext.constants list Constant *celem = ctx->constants; while(celem) { Constant *next = celem->next; free(celem->name); free(celem); celem = next; } // Free the ParseContext.controls list UVCXUControl *elem = ctx->controls; while(elem) { UVCXUControl *next = elem->next; xmlFree(elem->id); free(elem); elem = next; } free(ctx); } /** * Create a parsing context using the specified XML config-file * * @param file_name name (with an optional path) of the file to be parsed * @param info structure to pass operation flags and retrieve status information. * Can be NULL. * @param ctx address of a pointer to store the created context * * @return * - 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 */ static CResult create_context (const char *file_name, CDynctrlInfo *info, ParseContext **ctx_ret) { ParseContext *ctx; CResult ret; *ctx_ret = NULL; // Allocate memory for the parsing context ctx = (ParseContext *)malloc(sizeof(ParseContext)); if(!ctx) return C_NO_MEMORY; memset(ctx, 0, sizeof(*ctx)); ctx->info = info; // Parse the dynctrl configuration file ret = parse_dynctrl_file(file_name, ctx); if(ret) { destroy_context(ctx); return ret; } // Allocate a conversion descriptor ctx->cd = iconv_open("ASCII", "UTF-8"); if(ctx->cd == (iconv_t)-1) { destroy_context(ctx); return C_NO_MEMORY; } *ctx_ret = ctx; return C_SUCCESS; } /**************************************************************************************************/ /* Raw controls */ /**************************************************************************************************/ /*log functions*/ void wc_log_message(const char *format, ...) { va_list ap; va_start(ap, format); printf(PRINT_PREFIX); vprintf(format, ap); va_end(ap); printf("\n"); } void wc_log_error(const char *format, ...) { va_list ap; fprintf(stderr, PRINT_PREFIX "ERROR: "); va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, ".\n"); } void wc_log_warning(const char *format, ...) { va_list ap; fprintf(stderr, PRINT_PREFIX "Warning: "); va_start(ap, format); vfprintf(stderr, format, ap); va_end(ap); fprintf(stderr, ".\n"); } void wc_log_verbose(const char *format, ...) { va_list ap; if(!HAS_VERBOSE()) return; va_start(ap, format); printf(PRINT_PREFIX); vprintf(format, ap); va_end(ap); printf("\n"); } static int query_xu_control(int v4l2_dev, Control *control, uint8_t query, uint16_t size, void *data, const char *log_action) { struct uvc_xu_control_query xu_query = { .unit = control->uvc_unitid, .selector = control->uvc_selector, .query = query, .size = size, .data = data, }; if(ioctl(v4l2_dev, UVCIOC_CTRL_QUERY, &xu_query) != 0) { int res = errno; if(log_action == NULL) return res; const char *err; switch(res) { case ENOENT: err = "Extension unit or control not found"; break; case ENOBUFS: err = "Buffer size does not match control size"; break; case EINVAL: err = "Invalid request code"; break; case EBADRQC: err = "Request not supported by control"; break; default: err = strerror(res); break; } wc_log_error("Unable to %s XU control %s: %s. (System code: %d)", log_action, control->control.name, err, res); return res; } return 0; } /** * Queries information about a given raw control. * * This function uses a custom ioctl to send GET_LEN, GET_INFO, GET_MIN, GET_MAX, * GET_DEF, and GET_RES requests to the device and allocates the appropriate raw * buffers inside CControl. */ CResult init_xu_control(Device *device, Control *control) { CResult res = C_SUCCESS; int ret = 0; struct { CControlValue * value; uint8_t query; const char * action; } values[] = { { &control->control.min, UVC_GET_MIN, "query minimum value of" }, { &control->control.max, UVC_GET_MAX, "query maximum value of" }, { &control->control.def, UVC_GET_DEF, "query default value of" }, { &control->control.step, UVC_GET_RES, "query step size of " }, }; if(device == NULL || control == NULL || control->control.type != CC_TYPE_RAW) return C_INVALID_ARG; int v4l2_dev = open_v4l2_device(device->v4l2_name); if(v4l2_dev < 0) return C_INVALID_DEVICE; // Query the control length uint16_t length = 0; ret = query_xu_control(v4l2_dev, control, UVC_GET_LEN, sizeof(control->uvc_size), (void *)&length, "query size of"); control->uvc_size = le16toh(length); // The value from the device is always little-endian printf("query control size of : %d\n", control->uvc_size); if(ret != 0) { res = C_V4L2_ERROR; goto done; } if(control->uvc_size == 0) { wc_log_error("XU control %s reported a size of 0", control->control.name); res = C_INVALID_XU_CONTROL; goto done; } // Query the control information (i.e. flags such as supported requests) uint8_t info = 0; ret = query_xu_control(v4l2_dev, control, UVC_GET_INFO, sizeof(info), (void *)&info, "query information about"); if(ret != 0) { res = C_V4L2_ERROR; goto done; } control->control.flags = ((info & (1 << 0)) ? CC_CAN_READ : 0) | ((info & (1 << 1)) ? CC_CAN_WRITE : 0); printf("query control flags of: 0x%x\n", control->control.flags); // Query the min/max/def/res values unsigned int i = 0; for(i = 0; i < ARRAY_SIZE(values); i++) { CControlValue *value = values[i].value; printf("%s: ",values[i].action); // Allocate a buffer for the raw value value->type = control->control.type; value->raw.data = calloc(1, control->uvc_size); if(!value->raw.data) { res = C_NO_MEMORY; goto done; } value->raw.size = control->uvc_size; // Query the raw value ret = query_xu_control(v4l2_dev, control, values[i].query, control->uvc_size, value->raw.data, values[i].action); //print the resulting value in le and be format uint8_t * val = value->raw.data; int i=0; printf("(LE)0x"); for(i=0; iuvc_size; i++) { printf("%.2x", val[i]); } printf(" (BE)0x"); for(i=control->uvc_size-1; i >=0; i--) { printf("%.2x", val[i]); } printf("\n"); if(ret != 0) { res = C_V4L2_ERROR; goto done; } } done: if(res != C_SUCCESS) { for(i = 0; i < ARRAY_SIZE(values); i++) SAFE_FREE(values[i].value->raw.data); } close(v4l2_dev); return res; } /** * Create a libwebcam control from UVC control information. * * @param device Device to which the control should be appended. * @param entity GUID of the extension unit to which the control belongs. * @param unit_id UVC XU ID to which the control belongs. * @param selector UVC control selector of the control. * @param pret Pointer to receive the error code in the case of an error. * (Can be NULL.) * * @return * - NULL if an error occurred. The associated error can be found in @a pret. * - Pointer to the newly created control. */ static Control * create_xu_control (Device *device, unsigned char entity[], uint16_t unit_id, unsigned char selector, CResult *pret) { static unsigned int last_uvc_ctrl_id = CC_UVC_XU_BASE; assert(last_uvc_ctrl_id < 0xFFFFFFFF); CResult ret = C_SUCCESS; Control *ctrl = NULL; // Create the name for the control. // We don't have a meaningful name here, so we make it up from the GUID and selector. char *name = NULL; int r = asprintf(&name, GUID_FORMAT"/%u", GUID_ARGS(entity), selector); if(r <= 0) { ret = C_NO_MEMORY; goto done; } // Create the internal control info structure ctrl = (Control *)malloc(sizeof(*ctrl)); if(ctrl) { memset(ctrl, 0, sizeof(*ctrl)); ctrl->control.id = last_uvc_ctrl_id++; ctrl->uvc_unitid = unit_id; ctrl->uvc_selector = selector; ctrl->uvc_size = 0; // determined by init_xu_control() ctrl->control.name = name; ctrl->control.type = CC_TYPE_RAW; ctrl->control.flags = 0; // determined by init_xu_control() // Initialize the XU control (size, flags, min/max/def/res) ret = init_xu_control(device, ctrl); if(ret) goto done; ctrl->control.flags |= CC_IS_CUSTOM; // Add the new control to the control list of the given device ctrl->next = device->controls.first; device->controls.first = ctrl; device->controls.count++; } else { ret = C_NO_MEMORY; } done: if(ret != C_SUCCESS && ctrl) { SAFE_FREE(ctrl->control.name); SAFE_FREE(ctrl); } if(pret) *pret = ret; return ctrl; } /** * Retrieves the value of a given raw XU control. * * Returns a libwebcam status value to indicate the result of the operation and * sets the handle's last system error unless successful. * * If C_V4L2_ERROR is returned the last system error can mean the following: * ENOENT The UVC driver does not know the given control, i.e. the device does * does not support this particular control (or its extension unit). * ENOBUFS The buffer size does not match the size of the XU control. * EINVAL An invalid request code was passed. * EBADRQC The given request is not supported by the given control. * EFAULT The data pointer contains an invalid address. * * @return C_SUCCESS if the read was successful * C_INVALID_ARG if one of the arguments was NULL or a non-raw control was given * C_INVALID_DEVICE if the video device node could not be opened * C_BUFFER_TOO_SMALL if the value's raw buffer is NULL or its size too small * C_V4L2_ERROR if the UVC driver returned an error; check the handle's system error */ CResult read_xu_control(Device *device, Control *control, CControlValue *value, CHandle hDevice) { CResult res = C_SUCCESS; if(device == NULL || control == NULL || value == NULL || control->control.type != CC_TYPE_RAW) { printf("invalid arg\n"); return C_INVALID_ARG; } if(value->raw.data == NULL || value->raw.size < control->uvc_size) { printf("buffer to small\n"); return C_BUFFER_TOO_SMALL; } if(value->type != CC_TYPE_RAW) { printf("value not of raw type\n"); return C_INVALID_ARG; } int v4l2_dev = open_v4l2_device(device->v4l2_name); if(v4l2_dev < 0) return C_INVALID_DEVICE; int ret = query_xu_control(v4l2_dev, control, UVC_GET_CUR, control->uvc_size, value->raw.data, NULL); if(ret != 0) { set_last_error(hDevice, ret); res = C_V4L2_ERROR; goto done; } value->type = control->control.type; value->raw.size = control->uvc_size; done: close(v4l2_dev); return res; } /** * Sets the value of a given raw XU control. * * Returns a libwebcam status value to indicate the result of the operation and * sets the handle's last system error unless successful. * * If C_V4L2_ERROR is returned the last system error can mean the following: * ENOENT The UVC driver does not know the given control, i.e. the device does * does not support this particular control (or its extension unit). * ENOBUFS The buffer size does not match the size of the XU control. * EINVAL An invalid request code was passed. * EBADRQC The given request is not supported by the given control. * EFAULT The data pointer contains an invalid address. * * @return C_SUCCESS if the read was successful * C_INVALID_ARG if one of the arguments was NULL or a non-raw control was given or * the value's raw size does not match the control size * C_INVALID_DEVICE if the video device node could not be opened * C_V4L2_ERROR if the UVC driver returned an error; check the handle's system error */ CResult write_xu_control(Device *device, Control *control, const CControlValue *value, CHandle hDevice) { CResult res = C_SUCCESS; if(device == NULL || control == NULL || value == NULL || control->control.type != CC_TYPE_RAW) return C_INVALID_ARG; if(value->raw.size != control->uvc_size) return C_INVALID_ARG; if(value->type != CC_TYPE_RAW) return C_INVALID_ARG; int v4l2_dev = open_v4l2_device(device->v4l2_name); if(v4l2_dev < 0) return C_INVALID_DEVICE; int ret = query_xu_control(v4l2_dev, control, UVC_SET_CUR, control->uvc_size, value->raw.data, NULL); if(ret != 0) { set_last_error(hDevice, ret); res = C_V4L2_ERROR; } close(v4l2_dev); return res; } /* * API */ /** * 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 @a 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. * * @param file_name name of the device to open. * @param info structure to pass operation flags and retrieve status information. * Can be NULL. * * @return * - #C_INIT_ERROR if the library has not been initialized * - #C_INVALID_DEVICE if no supported devices are available * - #C_NO_MEMORY if memory could not be allocated * - #C_SUCCESS if the parsing was successful and no fatal error occurred * - #C_NOT_IMPLEMENTED if libwebcam was compiled with dynctrl support disabled */ CResult c_add_control_mappings_from_file (const char *file_name, CDynctrlInfo *info) { CResult ret = C_SUCCESS; CDevice *devices = NULL; ParseContext *ctx = NULL; if(!initialized) return C_INIT_ERROR; if(!file_name) return C_INVALID_ARG; // Enumerate the devices and abort if there are no devices present unsigned int size = 0, device_count = 0; ret = c_enum_devices(NULL, &size, &device_count); if(ret == C_SUCCESS) { // Our zero buffer was large enough, so no devices are present return C_INVALID_DEVICE; } else if(ret != C_BUFFER_TOO_SMALL) { // Something bad has happened, so bail out return ret; } assert(device_count > 0); devices = (CDevice *)malloc(size); ret = c_enum_devices(devices, &size, &device_count); if(ret) goto done; ret = create_context(file_name, info, &ctx); if(ret) goto done; // Loop through the devices and check which ones have a supported uvcvideo driver behind them int i, successful_devices = 0; for(i = 0; i < device_count; i++) { CDevice *device = &devices[i]; // Skip non-UVC devices if(strcmp(device->driver, "uvcvideo") != 0) { add_info(ctx, "device '%s' skipped because it is not a UVC device.", device->shortName ); continue; } // Create a device handle ctx->handle = c_open_device(device->shortName); if(!ctx->handle) { add_error(ctx, "device '%s' skipped because it could not be opened.", device->shortName ); continue; } ctx->device = device; // Add the parsed control mappings to this device ret = add_control_mappings(ctx); if(ret == C_SUCCESS) { successful_devices++; } // Close the device handle c_close_device(ctx->handle); ctx->handle = 0; ctx->device = NULL; } if(successful_devices == 0) ret = C_INVALID_DEVICE; done: destroy_context(ctx); if(devices) free(devices); return ret; } /** * Parses a dynamic controls configuration file and adds the contained controls and * control mappings to the UVC device pointed to by the passed in handle. * * Notes: * - If the @a 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. * * @param handle handle to the device to add control mappings to * @param file_name name of the controls configuration file * @param info structure to pass operation flags and retrieve status information. * Can be NULL. * * @return * - #C_INIT_ERROR if the library has not been initialized * - #C_NO_MEMORY if memory could not be allocated * - #C_SUCCESS if the parsing was successful and no fatal error occurred * - #C_NOT_IMPLEMENTED if libwebcam was compiled with dynctrl support disabled */ CResult c_add_control_mappings (CHandle handle, const char *file_name, CDynctrlInfo *info) { CResult ret; CDevice *device = NULL; ParseContext *ctx = NULL; unsigned int size = 0; if(!initialized) return C_INIT_ERROR; if(!handle) return C_INVALID_ARG; if(!file_name) return C_INVALID_ARG; ret = c_get_device_info(handle, NULL, device, &size); if(ret != C_BUFFER_TOO_SMALL) { // Something bad has happened, so bail out return ret; } device = (CDevice *)malloc(size); ret = c_get_device_info(handle, NULL, device, &size); if(ret) goto done; ret = create_context(file_name, info, &ctx); if(ret) goto done; ctx->handle = handle; ctx->device = device; ret = add_control_mappings(ctx); done: destroy_context(ctx); free(device); return ret; } #else CResult c_add_control_mappings_from_file (const char *file_name, CDynctrlInfo *info) { return C_NOT_IMPLEMENTED; } CResult c_add_control_mappings (CHandle handle, const char *file_name, CDynctrlInfo *info) { return C_NOT_IMPLEMENTED; } #endif libwebcam-src-0.2.4/common/0000755000175000017500000000000012234547770014554 5ustar paulopaulolibwebcam-src-0.2.4/common/build/0000755000175000017500000000000012234547770015653 5ustar paulopaulolibwebcam-src-0.2.4/common/build/cmake_try_v4l2_ctrl_type_string.c0000644000175000017500000000021012234547770024310 0ustar paulopaulo#include int main() { v4l2_ctrl_type t = V4L2_CTRL_TYPE_STRING; struct v4l2_ext_control s; s.size; s.string; } libwebcam-src-0.2.4/common/build/CPackConfig.cmake.conf0000644000175000017500000000354412234547770021716 0ustar paulopaulo# Set the variables from the CMakeLists.txt files SET(CPACK_GENERATOR "${CPACK_GENERATOR}") SET(CPACK_PACKAGE_NAME "${CPACK_PACKAGE_NAME}") SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${CPACK_PACKAGE_DESCRIPTION_SUMMARY}") SET(CPACK_PACKAGE_DESCRIPTION "${CPACK_PACKAGE_DESCRIPTION}") SET(CPACK_PACKAGE_VENDOR "${CPACK_PACKAGE_VENDOR}") SET(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION}") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}") SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_DEBIAN_PACKAGE_MAINTAINER}") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "${CPACK_DEBIAN_PACKAGE_DEPENDS}") SET(CPACK_DEBIAN_PACKAGE_ARCHITECTURE "${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") SET(CPACK_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") SET(CPACK_OUTPUT_CONFIG_FILE "${CMAKE_CURRENT_BINARY_DIR}/CPackConfig.cmake") # The third argument is the component. In our case we have one component per # project with the same name as the project. We only want to install that one # for the packaging process, otherwise (with the default 'ALL') we would end # up with the libwebcam files contained inside the uvcdynctrl package. SET(CPACK_INSTALL_CMAKE_PROJECTS ".;${PROJECT_NAME};${PROJECT_NAME};/") # These are standard and were generated by CMake SET(CPACK_CMAKE_GENERATOR "Unix Makefiles") SET(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") SET(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") SET(CPACK_MODULE_PATH "") SET(CPACK_PACKAGE_DEFAULT_LOCATION "/") SET(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-2.6/Templates/CPack.GenericDescription.txt") SET(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-2.6/Templates/CPack.GenericLicense.txt") SET(CPACK_RESOURCE_FILE_README "/usr/share/cmake-2.6/Templates/CPack.GenericDescription.txt") SET(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-2.6/Templates/CPack.GenericWelcome.txt") SET(CPACK_SET_DESTDIR "OFF") SET(CPACK_SYSTEM_NAME "Linux") SET(CPACK_TOPLEVEL_TAG "Linux") libwebcam-src-0.2.4/common/include/0000755000175000017500000000000012234547770016177 5ustar paulopaulolibwebcam-src-0.2.4/common/include/webcam.h0000755000175000017500000005351112234547770017616 0ustar paulopaulo/** * \file * Webcam library interface definition. * * \ingroup libwebcam */ /* * Copyright (c) 2006-2007 Logitech. * * This file is part of libwebcam. * * libwebcam is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libwebcam 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with libwebcam. If not, see . */ #ifndef C_WEBCAM_H #define C_WEBCAM_H #include #include #include "dynctrl-logitech.h" /* * Basic type definitions */ /// Device handle for libwebcam typedef unsigned int CHandle; /// Function return type for libwebcam typedef unsigned int CResult; /* * Enums */ /** * Return values for libwebcam functions. */ enum _CResults { C_SUCCESS = 0, ///< Success C_NOT_IMPLEMENTED, ///< The function is not implemented C_INIT_ERROR, ///< Error during initialization or library not initialized C_INVALID_ARG, ///< Invalid argument C_INVALID_HANDLE, ///< Invalid handle C_INVALID_DEVICE, ///< Invalid device or device cannot be opened C_NOT_EXIST, ///< The device to which the handle points no longer exists C_NOT_FOUND, ///< Object not found C_BUFFER_TOO_SMALL, ///< Buffer too small C_SYNC_ERROR, ///< Error during data synchronization // 10: C_NO_MEMORY, ///< Out of memory C_NO_HANDLES, ///< Out of handles C_V4L2_ERROR, ///< A Video4Linux2 API call returned an unexpected error C_SYSFS_ERROR, ///< A sysfs file access returned an error C_PARSE_ERROR, ///< A control could not be parsed C_CANNOT_WRITE, ///< Writing not possible (e.g. read-only control) C_CANNOT_READ, ///< Reading not possible (e.g. write-only control) C_INVALID_XU_CONTROL, ///< Invalid XU control has been encountered C_SYSTEM_ERROR, ///< An system call returned an unexpected error C_DEVICE_BUSY, ///< The device is busy // 20: C_WRONG_STATE, ///< The requested operation is invalid at this point C_INVALID_FORMAT, ///< The requested format is not available or not supported C_CONVERSION_ERROR, ///< The format conversion failed (invalid format, buffer size, etc.) }; /** * Control identifiers. * This is an exhaustive list of all controls supported by libwebcam. As new * controls appear, these should be added to this list. */ typedef enum _CControlId { // UVC: Basic image control CC_BRIGHTNESS = 1, ///< Image brightness CC_CONTRAST, ///< Image contrast CC_GAIN, ///< Gain control CC_SATURATION, ///< Image color saturation CC_HUE, ///< Hue CC_GAMMA, ///< Gamma correction CC_SHARPNESS, ///< Image sharpness // UVC: Advanced image control /// White balance color temperature CC_WHITE_BALANCE_TEMPERATURE, /// Enable/disable automatic while balance color temperature selection CC_AUTO_WHITE_BALANCE_TEMPERATURE, /// White balance color component control (red, blue) CC_WHITE_BALANCE_COMPONENT, /// Enable/disable automatic white balance color component selection CC_AUTO_WHITE_BALANCE_COMPONENT, /// Backlight compensation mode CC_BACKLIGHT_COMPENSATION, /// Local power line frequency for anti-flicker processing CC_POWER_LINE_FREQUENCY, /// Enable/disable automatic hue control CC_AUTO_HUE, /// Mode for automatic exposure control CC_AUTO_EXPOSURE_MODE, /// Constraints for automatic exposure control (e.g. adaptive vs. constant frame rate) CC_AUTO_EXPOSURE_PRIORITY, /// Length of exposure (electronic shutter speed) CC_EXPOSURE_TIME_ABSOLUTE, /// Relative change to the current length of exposure CC_EXPOSURE_TIME_RELATIVE, /// Auto brightness CC_AUTO_BRIGHTNESS, // UVC: Optics control /// Enable/disable automatic focus adjustment CC_AUTO_FOCUS, /// Distance to optimally focused target CC_FOCUS_ABSOLUTE, /// Relative change in distance to currently focused target CC_FOCUS_RELATIVE, /// Aperture setting CC_IRIS_ABSOLUTE, /// Relative change to the current aperture setting CC_IRIS_RELATIVE, /// Objective lens focal length CC_ZOOM_ABSOLUTE, /// Relative change to the current objective lens focal length CC_ZOOM_RELATIVE, /// Digital zoom multiplier applied to the optical image CC_DIGITAL_ZOOM, // UVC: Motion control /// Pan angle (rotation on a vertical axis) CC_PAN_ABSOLUTE, /// Relative change to the current pan angle CC_PAN_RELATIVE, /// Tilt angle (rotation in a vertical plane) CC_TILT_ABSOLUTE, /// Relative change to the current tilt angle CC_TILT_RELATIVE, /// Roll angle (rotation along the image viewing axis) CC_ROLL_ABSOLUTE, /// Relative change to the current roll angle CC_ROLL_RELATIVE, // UVC: Misc /// Temporarily prevent image from being acquired CC_PRIVACY, // V4L2: Motion control (new since 2.6.26) /// Reset pan angle to a safe default value. CC_PAN_RESET, /// Reset tilt angle to a safe default value. CC_TILT_RESET, // V4L2: Unknown controls /// Base for unknown V4L2 controls CC_V4L2_BASE = 0x1000, /// Base for custom V4L2 driver controls CC_V4L2_CUSTOM_BASE = 0x2000, /// Base for unknown V4L2 MPEG controls CC_V4L2_MPEG_BASE = 0x3000, /// Base for unknown V4L2 camera class controls CC_V4L2_CAMERA_CLASS_BASE = 0x4000, // Logitech (USB vendor ID: 0x046d) CC_LOGITECH_BASE = 0x046d0000, /// Relative change to the current pan and tilt angles. /// This control is specific to Logitech cameras that support panning and /// tilting such as the QuickCam Orbit series. CC_LOGITECH_PANTILT_RELATIVE, /// Reset pan and tilt angles to a safe default value. /// This control is specific to Logitech cameras that support panning and /// tilting such as the QuickCam Orbit series. CC_LOGITECH_PANTILT_RESET, // Illumination mode of the first LED. CC_LOGITECH_LED1_MODE, // Blinking frequency of the first LED. CC_LOGITECH_LED1_FREQUENCY, // Disable video processing (enable raw mode) CC_LOGITECH_DISABLE_PROCESSING, // Bits per pixel for raw (Bayer) mode CC_LOGITECH_RAW_BITS_PER_PIXEL, // CC_LOGITECH_USB_VID, // CC_LOGITECH_USB_PID, // CC_LOGITECH_USB_BCD, /// Base for raw UVC controls CC_UVC_XU_BASE = 0xFFFF0000, } CControlId; /** * Flags specifying control properties and capabilities. */ typedef enum _CControlFlags { /// The control can be read, i.e. its current value can be queried. /// This flag is usually not set for action controls. CC_CAN_READ = 1 << 0, /// The control can be changed, i.e. it can be set to a new value. /// Note that this flag does not imply CC_CAN_READ. Action controls accept /// values but cannot necessarily be queried. CC_CAN_WRITE = 1 << 1, /// The control supports value change notification. CC_CAN_NOTIFY = 1 << 2, // The control is a custom vendor control and not standardized in V4L2 or UVC. CC_IS_CUSTOM = 1 << 8, // Set values are interpreted as being relative to the current value. CC_IS_RELATIVE = 1 << 9, // The control triggers an action. CC_IS_ACTION = 1 << 10, //The control needs to be set (used for save/restore) CC_NEED_SET = 1 << 11, } CControlFlags; /** * Types for controls. * These types give both hints to graphical user interfaces on how to display * the control to the user as well as to the implementation in terms of data * length required to store control values. */ typedef enum _CControlType { /// The control uses raw binary data. /// Usually (but not necessarily) this includes values that cannot be easily /// mapped to simple data types. CC_TYPE_RAW = 1, /// The control knows only one enabled/disabled state. /// Controls of this type are typically displayed as checkboxes. CC_TYPE_BOOLEAN, /// The control accepts a defined list of values. /// Controls of this type are typically displayed as combo boxes or lists. CC_TYPE_CHOICE, /// The control accepts 8-bit integer values. CC_TYPE_BYTE, /// The control accepts 16-bit integer values. CC_TYPE_WORD, /// The control accepts 32-bit integer values. CC_TYPE_DWORD, /// The control accepts 32-bit unsigned values. CC_TYPE_BUTTON, } CControlType; /** * Event identifiers. */ typedef enum _CEventId { CE_CONTROL_INVALID = 0, } CEventId; /** * Flags specifying properties of events. */ typedef enum _CEventFlags { CE_INVALID = 0, } CEventFlags; /** * Types of frame size specifications. */ typedef enum _CFrameSizeTypes { /// One discrete width/height combination. CF_SIZE_DISCRETE = 1, /// Minimum and maximum values for both width and height. CF_SIZE_CONTINUOUS, /// Minimum, maximum, and step values for both width and height. CF_SIZE_STEPWISE, } CFrameSizeTypes; /** * Types of frame interval specification. */ typedef enum _CFrameIntervalTypes { /// One discrete time interval. CF_INTERVAL_DISCRETE = 1, /// Minimum and maximum values for the time interval. CF_INTERVAL_CONTINUOUS, /// Minimum, maximum, and step values for the time interval. CF_INTERVAL_STEPWISE, } CFrameIntervalTypes; /** * Flags specifying control properties and capabilities. */ typedef enum _CDynctrlFlags { /// Disable XML schema validation. CD_DONT_VALIDATE = 1 << 0, /// Collect errors and warnings during the process CD_REPORT_ERRORS = 1 << 1, /// Return meta data during the XML parsing process CD_RETRIEVE_META_INFO = 1 << 2, } CDynctrlFlags; /** * Severity levels for messages returned by the dynamic control functions */ typedef enum _CDynctrlMessageSeverity { CD_SEVERITY_ERROR = 2, ///< Error CD_SEVERITY_WARNING = 3, ///< Warning CD_SEVERITY_INFO = 4, ///< Informational } CDynctrlMessageSeverity; /* * Structs */ /** * USB specific information about a device. */ typedef struct _CUSBInfo { /// The vendor ID. unsigned short vendor; /// The product ID. unsigned short product; /// The product revision number. unsigned short release; } CUSBInfo; /** * Webcam device information. */ typedef struct _CDevice { /// A unique short name. /// For V4L2 devices this is the name of the device file. For example, if /// a device appears as '/dev/video0', the short name is 'video0'. /// This member is never NULL. char * shortName; /// The human-readable name of the device. /// This member is never NULL. char * name; /// The name of the driver providing the camera interface. /// This member is never NULL. char * driver; /// The location of the camera. /// This string is dependent on the implementation that provides the device. /// It could either be a string provided by the driver or a device name. /// This member is never NULL. char * location; /// USB related information about the camera. CUSBInfo usb; } CDevice; /** * A raw control value. */ typedef struct _CControlRawValue { /// Pointer to the raw data. /// Note: Callers must allocate and free this buffer by themselves. void * data; /// Size of the raw data. /// For controls of type #CC_TYPE_RAW this size must be at least as big as /// the CControl.max.raw.size value of the control in question. /// For controls of type #CC_TYPE_STRING this size minus one must be between the /// the CControl.string.min_length and CControl.string.max_length values /// and must be a multiple of the CControl.string.length_step value. unsigned int size; } CControlRawValue; /** * A value of a control. */ typedef struct _CControlValue { /// The type of the control to which the value belongs. /// This member is used to determine which of the members of the union are /// valid. The type is a duplicate of the corresponding CControl#type value. CControlType type; union { /// The value of the control for number based controls. /// This member is valid for the following control types: /// #CC_TYPE_BOOLEAN, #CC_TYPE_CHOICE, #CC_TYPE_BYTE, /// #CC_TYPE_WORD, #CC_TYPE_DWORD #CC_TYPE_BUTTON int value; /// The value of the control for raw cntrols. /// This member is valid only for control type #CC_TYPE_RAW. CControlRawValue raw; /// The value of the control for string controls. /// This member is valid only for control type #CC_TYPE_STRING. CControlRawValue string; }; } CControlValue; /** * A list of choices for a choice type of control. * @see CC_TYPE_CHOICE */ typedef struct _CControlChoice { /// The index of the choice within the list of choices. /// Note that this index is not necessarily zero-based and can therefore @a not /// be used as an index into CControl#choices#list[]. int index; int id; /// The name of the choice. /// This member is never NULL. char name[32]; } CControlChoice; /** * A description of a camera control. */ typedef struct _CControl { /// The identifier of the control CControlId id; /// The human-readable name of the control char * name; /// The type of the control CControlType type; /// Flags describing properties and capabilities of the control CControlFlags flags; /// The current value of the control CControlValue value; /// The default value of the control CControlValue def; union { /// Additional control attributes for non-choice controls. /// The members of this struct are only valid for control types other /// than #CC_TYPE_CHOICE. struct { /// The minimum value of the control CControlValue min; /// The maximum value of the control CControlValue max; /// The resolution of the control values CControlValue step; }; /// List of the possible choices that this control allows. /// The members of this struct are only valid if the type is #CC_TYPE_CHOICE. struct { /// The number of choices in the list unsigned int count; /// The list of choice values CControlChoice * list; /// A buffer that contains the names of the #CControlChoice items. /// The @a name fields of the items point to strings within this buffer, /// so there is no need to work with this member directly except /// freeing the buffer if the control is disposed of. //char * names; } choices; /// Attributes for string controls. /// The members of this struct are only valid if the type is #CC_TYPE_STRING. /// Note that the length values do not include the terminating null byte. struct { /// The minimum number of characters required unsigned int min_length; /// The maximum number of characters allowed unsigned int max_length; /// The value of which the string length has to be a multiple unsigned int length_step; } string; }; } CControl; /** * A description of a pixel format. */ typedef struct _CPixelFormat { /// A FourCC code identifying the pixel format. /// Note that this member contains an extra byte which will contain a \\0 /// character when returned by c_enum_pixel_formats(). This allows the field /// to be treated like a NUL terminated string. char fourcc[5]; /// A human-readable description of the pixel format. char * name; /// The MIME type corresponding to the pixel format. /// This member can be NULL. char * mimeType; } CPixelFormat; /** * A description of one or multiple frame sizes. */ typedef struct _CFrameSize { /// Type of the frame size(s) described (discrete, continuous, step-wise) CFrameSizeTypes type; union { /// Discrete frame size. /// This member is only valid if @a type is #CF_SIZE_DISCRETE. struct { /// Width unsigned int width; /// Height unsigned int height; }; /// Continuous or step-wise frame size. /// This member is only valid if @a type is #CF_SIZE_CONTINUOUS or /// #CF_SIZE_STEPWISE. struct { /// Minimum width unsigned int min_width; /// Maximum width unsigned int max_width; /// Step size for the width (usually 1 if @a type is #CF_SIZE_CONTINUOUS) unsigned int step_width; /// Minimum height unsigned int min_height; /// Maximum height unsigned int max_height; /// Step size for the height (usually 1 if @a type is #CF_SIZE_CONTINUOUS) unsigned int step_height; }; }; } CFrameSize; /** * A description of one or multiple frame intervals. * Each frame interval is described as a fraction of a second. */ typedef struct _CFrameInterval { /// Type of the frame interval(s) described (discrete, continuous, step-wise) CFrameIntervalTypes type; union { /// Discrete frame interval. /// This member is only valid if @a type is #CF_INTERVAL_DISCRETE. struct { /// Numerator of the frame interval unsigned int n; /// Denominator of the frame interval unsigned int d; }; /// Continuous or step-wise frame interval. /// This member is only valid if @a type is #CF_INTERVAL_CONTINUOUS or /// #CF_INTERVAL_STEPWISE. struct { /// Numerator of the minimum frame interval unsigned int min_n; /// Denominator of the minimum frame interval unsigned int min_d; /// Numerator of the maximum frame interval unsigned int max_n; /// Denominator of the maximum frame interval unsigned int max_d; /// Numerator of the frame interval step size (usually 1 if @a type is #CF_INTERVAL_CONTINUOUS unsigned int step_n; /// Denominator of the frame interval step size (usually 1 if @a type is #CF_INTERVAL_CONTINUOUS unsigned int step_d; }; }; } CFrameInterval; /** * An event descriptor. */ typedef struct _CEvent { /// Unique identifier of the event CEventId id; /// Human-readable name of the event char * name; /// Flags descripting properties of the event CEventFlags flags; } CEvent; /** * Message returned by the dynamic control configuration parser. */ typedef struct _CDynctrlMessage { /// Line number that the message concerns int line; /// Column that the message concerns int col; /// Severity level CDynctrlMessageSeverity severity; /// Pointer to the message text char * text; } CDynctrlMessage; /** * Version number in the "major.minor" format. */ typedef struct _CVersionNumber { /// Major version number unsigned int major; /// Minor version number unsigned int minor; } CVersionNumber; /** * Statistics on the number of list elements that were processed. */ typedef struct _CDynctrlInfoListStats { /// Number of elements in the list that were processed successfully unsigned int successful; /// Number of elements in the list that could not be processed successfully unsigned int failed; } CDynctrlInfoListStats; /** * Input flags and output data used/returned by the control configuration parser. */ typedef struct _CDynctrlInfo { /// Flags controlling operations related to dynamic controls CDynctrlFlags flags; /// Processing statistics struct { /// Statistics on the constants that were processed CDynctrlInfoListStats constants; /// Statistics on the controls that were processed CDynctrlInfoListStats controls; /// Statistics on the mappings that were processed CDynctrlInfoListStats mappings; } stats; /// Meta information about the XML control configuration struct { /// File format version CVersionNumber version; /// Name of the configuration author char * author; /// Contact information of the configuration author (e.g. e-mail address) char * contact; /// Copyright information about the configuration file char * copyright; /// Revision number of the configuration file (configuration version) CVersionNumber revision; } meta; /// Number of messages in the @a messages array unsigned int message_count; /// Pointer to the array with the messages concerning the operation CDynctrlMessage * messages; } CDynctrlInfo; /* * Type definitions */ /** * Prototype for event handlers */ typedef void (*CEventHandler)(CHandle hDevice, CEventId event_id, void *context); /* * Functions */ #ifdef __cplusplus extern "C" { #endif extern CResult c_init (void); extern void c_cleanup (void); extern CHandle c_open_device (const char *device_name); extern void c_close_device (CHandle hDevice); extern CResult c_enum_devices (CDevice *devices, unsigned int *size, unsigned int *count); extern CResult c_get_device_info (CHandle hDevice, const char *device_name, CDevice *info, unsigned int *size); extern CResult c_enum_pixel_formats (CHandle hDevice, CPixelFormat *formats, unsigned int *size, unsigned int *count); extern CResult c_enum_frame_sizes (CHandle hDevice, const CPixelFormat *pixelformat, CFrameSize *sizes, unsigned int *size, unsigned int *count); extern CResult c_enum_frame_intervals (CHandle hDevice, const CPixelFormat *pixelformat, const CFrameSize *framesize, CFrameInterval *intervals, unsigned int *size, unsigned int *count); extern CResult c_enum_controls (CHandle hDevice, CControl *controls, unsigned int *size, unsigned int *count); extern CResult c_set_control (CHandle hDevice, CControlId control_id, const CControlValue *value); extern CResult c_get_control (CHandle hDevice, CControlId control_id, CControlValue *value); extern CResult c_save_controls (CHandle hDevice, const char *filename); extern CResult c_load_controls (CHandle hDevice, const char *filename); extern CResult c_enum_events (CHandle hDevice, CEvent *events, unsigned int *size, unsigned int *count); extern CResult c_subscribe_event (CHandle hDevice, CEventId event_id, CEventHandler handler, void *context); extern CResult c_unsubscribe_event (CHandle hDevice, CEventId event_id); #ifndef DISABLE_UVCVIDEO_DYNCTRL extern CResult c_add_control_mappings_from_file (const char *file_name, CDynctrlInfo *info); extern CResult c_add_control_mappings (CHandle handle, const char *file_name, CDynctrlInfo *info); extern CResult c_read_xu_control(CHandle hDevice, unsigned char entity[], uint16_t unit_id, unsigned char selector, CControlValue *value); extern CResult c_write_xu_control(CHandle hDevice, unsigned char entity[], uint16_t unit_id, unsigned char selector, CControlValue *value); #endif extern char *c_get_error_text (CResult error); extern char *c_get_handle_error_text (CHandle hDevice, CResult error); #ifdef __cplusplus } #endif #endif /* C_WEBCAM_H */ libwebcam-src-0.2.4/common/include/dynctrl-logitech.h0000644000175000017500000000420212234547770021621 0ustar paulopaulo /* * UVC dynamic control mapping header file * * This file has been dynamically generated using the include.xsl XSLT * transform stylesheet from a dynamic control mapping configuration file. * * Version: 1.0 * Author: Martin Rubli, Logitech * Contact: http://www.quickcamteam.net/ * Revision: 0.16 * * Copyright (c) 2006-2008 Logitech */ /* Start constants */ #ifndef UVC_GUID_LOGITECH_USER_HW_CONTROL #define UVC_GUID_LOGITECH_USER_HW_CONTROL { \ 0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x1f \ } #endif #ifndef UVC_GUID_LOGITECH_VIDEO_PIPE #define UVC_GUID_LOGITECH_VIDEO_PIPE { \ 0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x50 \ } #endif #ifndef UVC_GUID_LOGITECH_MOTOR_CONTROL #define UVC_GUID_LOGITECH_MOTOR_CONTROL { \ 0x82, 0x06, 0x61, 0x63, 0x70, 0x50, 0xab, 0x49, \ 0xb8, 0xcc, 0xb3, 0x85, 0x5e, 0x8d, 0x22, 0x56 \ } #endif #ifndef XU_HW_CONTROL_LED1 #define XU_HW_CONTROL_LED1 1 #endif #ifndef XU_COLOR_PROCESSING_DISABLE #define XU_COLOR_PROCESSING_DISABLE 5 #endif #ifndef XU_RAW_DATA_BITS_PER_PIXEL #define XU_RAW_DATA_BITS_PER_PIXEL 8 #endif #ifndef XU_MOTORCONTROL_PANTILT_RELATIVE #define XU_MOTORCONTROL_PANTILT_RELATIVE 1 #endif #ifndef XU_MOTORCONTROL_PANTILT_RESET #define XU_MOTORCONTROL_PANTILT_RESET 2 #endif #ifndef XU_MOTORCONTROL_FOCUS #define XU_MOTORCONTROL_FOCUS 3 #endif #ifndef V4L2_CID_PAN_RELATIVE #define V4L2_CID_PAN_RELATIVE 0x009A0904 #endif #ifndef V4L2_CID_TILT_RELATIVE #define V4L2_CID_TILT_RELATIVE 0x009A0905 #endif #ifndef V4L2_CID_PAN_RESET #define V4L2_CID_PAN_RESET 0x009A0906 #endif #ifndef V4L2_CID_TILT_RESET #define V4L2_CID_TILT_RESET 0x009A0907 #endif #ifndef V4L2_CID_FOCUS #define V4L2_CID_FOCUS 0x0A046D04 #endif #ifndef V4L2_CID_LED1_MODE #define V4L2_CID_LED1_MODE 0x0A046D05 #endif #ifndef V4L2_CID_LED1_FREQUENCY #define V4L2_CID_LED1_FREQUENCY 0x0A046D06 #endif #ifndef V4L2_CID_DISABLE_PROCESSING #define V4L2_CID_DISABLE_PROCESSING 0x0A046D71 #endif #ifndef V4L2_CID_RAW_BITS_PER_PIXEL #define V4L2_CID_RAW_BITS_PER_PIXEL 0x0A046D72 #endif /* End constants */ libwebcam-src-0.2.4/cleandoc.sh0000755000175000017500000000010412234547770015366 0ustar paulopaulo#!/bin/sh set -e export DOCDIR="./doxygen-output" rm -rf $DOCDIR libwebcam-src-0.2.4/README0000644000175000017500000000623212234547770014147 0ustar paulopauloWebcam Library and Tools ======================== Introduction ------------ The webcam-tools package contains the following two components: - libwebcam Webcam Library - uvcdynctrl Manage dynamic controls in uvcvideo This README file contains information that is common to all of the above components. For component specific information please refer to the README files in the libwebcam/ and uvcdynctrl/ subdirectories. Versions -------- Note that the latest versions of the Webcam Library, its API documentation, and the tools can always be found at the following address: http://sourceforge.net/p/libwebcam Dependencies ------------ The Webcam Tools have the following external dependencies: - kernel headers (linux/videodev2.h and linux/uvcvideo.h) - LibXML 2 development files (usually from the libxml2-dev package) - gengetopt (optional) gengetopt (optional): The uvcdynctrl directory ships with the two files cmdline.[ch]. As long as those are present, gnugetopt is not required. If they are missing, the build process will try to create them with the help of gnugetopt. V4L2 2.6.32 (optional): To take advantage of the raw/string control support version 2.6.32 of V4L2 is required. To be more specific: V4L2_CTRL_TYPE_STRING needs to be supported. Whether this is the case is determined at build time and if string control support is not present in your version of V4L2 the corresponding feature in libwebcam is disabled. During the build process one of the following messages is displayed indicating the result of the test: ** Your V4L2 has V4L2_CTRL_TYPE_STRING support. Enabling raw control support. ** Your V4L2 does not have V4L2_CTRL_TYPE_STRING support. Compiling without raw control support. Note that the uvcvideo version that comes with 2.6.32 does not yet support string controls. At the time of this writing support for it is being added to the UVC driver, so future versions should support it, therefore allowing V4L2 control values to be more than 4 bytes long. Building -------- The build system is based on CMake. Because of the way CMake works, Makefiles do not ship with libwebcam, so you have to have CMake installed. Don't worry, though, you are likely to have much fewer illegible error messages than with the previous GNU Automake. Once you have CMake installed you can build and install it by running the following commands in the webcam-tools top level source directory: mkdir build cd build cmake .. make make install (as root) You need at least CMake 2.6, so if you are running Ubuntu 8.04 you need to enable the hardy-backports repository in /etc/apt/sources.list and update the 'cmake' package. CMake defaults to installing binaries and libraries to /usr/local. To use a different install prefix, you can add a command line parameter to 'cmake' like this: cmake .. -DCMAKE_INSTALL_PREFIX=/usr If you prefer to leave the prefix alone, you should make sure that /usr/local/bin is in your path and LD_LIBRARY_PATH contains the /usr/local/lib directory. Questions and feedback ---------------------- Please feel free to post your questions and comments at the sourceforge project page: http://sourceforge.net/p/libwebcam libwebcam-src-0.2.4/makedoc.sh0000755000175000017500000000065412234547770015233 0ustar paulopaulo#!/bin/bash set -e export SRCDIR="." export DOCDIR="./doxygen-output" export CONFIG="doxygen/libwebcam.cfg" echo "Cleaning up output directory '$DOCDIR' ..." rm -rf $DOCDIR echo -e "Done.\n" echo "Generating Doxygen documentation using configuration file '$CONFIG' ..." mkdir -p $DOCDIR doxygen $CONFIG echo -e "Done.\n" echo "Copying extra resource files ..." cp -v doxygen/res/* $DOCDIR/libwebcam/html/ echo -e "Done.\n"