1 /* print-camera-list - print libgphoto2 camera list in different formats
3 * Copyright © 2002,2005 Hans Ulrich Niedermann <hun@users.sourceforge.net>
4 * Portions Copyright © 2002 Lutz Müller <lutz@users.sourceforge.net>
5 * Portions Copyright © 2005 Julien BLACHE <jblache@debian.org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #define GP_USB_HOTPLUG_SCRIPT "usbcam"
26 /* Not sure whether this is the best possible name */
27 #define ARGV0 "print-camera-list"
30 ARGV0 " - print libgphoto2 camera list in different formats" \
33 " " ARGV0 " [<options>] <FORMAT> [<format specific arguments>]\n" \
36 " --debug print all debug output\n" \
37 " --help print this help message\n" \
38 " --verbose also print comments with camera model names\n" \
40 ARGV0 " prints the camera list in the specified format FORMAT on stdout.\n" \
42 "All other messages are printed on stderr. In case of any error, the \n" \
43 "program aborts regardless of data printed on stdout and returns a non-zero\n" \
46 #ifdef _GPHOTO2_SAMSUNG_PATCH_
47 #define RM_CMD "/bin/rm -rf"
48 #define MKDIR_CMD "/bin/mkdir -p"
49 #define TOUCH_CMD "/bin/touch"
50 #define CAMERA_NAME_INFO_PATH "/tmp/camera"
51 #define SYS_EVENT_PATH "/usr/bin/sys_event"
52 #define SYS_CAMERA_ADD_EVENT "device_camera_add"
53 #define SYS_CAMERA_REMOVE_EVENT "device_camera_remove"
62 #include <gphoto2/gphoto2-camera.h>
63 #include <gphoto2/gphoto2-port-log.h>
65 /* for detailed version message */
66 #include <gphoto2/gphoto2-version.h>
79 GPVersionFunc version_func;
82 const module_version module_versions[] = {
83 { "libgphoto2", gp_library_version },
84 { "libgphoto2_port", gp_port_library_version },
88 typedef char *string_array_t[];
90 typedef string_array_t *string_array_p;
93 int number_of_cameras;
100 typedef int (* begin_func_t) (const func_params_t *params,
102 typedef int (* middle_func_t) (const func_params_t *params,
104 typedef int (* camera_func_t) (const func_params_t *params,
107 const CameraAbilities *ca,
109 typedef int (* end_func_t) (const func_params_t *params,
113 #define GP_USB_HOTPLUG_MATCH_VENDOR_ID 0x0001
114 #define GP_USB_HOTPLUG_MATCH_PRODUCT_ID 0x0002
116 #define GP_USB_HOTPLUG_MATCH_INT_CLASS 0x0080
117 #define GP_USB_HOTPLUG_MATCH_INT_SUBCLASS 0x0100
118 #define GP_USB_HOTPLUG_MATCH_INT_PROTOCOL 0x0200
126 fprintf(stderr, ARGV0 ": " \
127 "Fatal error running `%s'.\n" \
128 "Aborting.\n", #result ); \
132 #else /* !__GNUC__ */
137 fprintf(stderr, ARGV0 ": " \
138 "Fatal error detected, aborting.\n"); \
142 #endif /* __GNUC__ */
144 #define FATAL(msg...) \
146 fprintf(stderr, ARGV0 ": Fatal: " msg); \
147 fprintf(stderr, "\n"); \
151 #define ASSERT(cond) \
154 FATAL("Assertion failed: %s", #cond); \
159 /* print_version_comment
160 * Print comment to output containing information on library versions
162 * out the file to write the comment to
163 * startline printed at the start of each line, e.g. "# " or " | "
164 * endline printed as the end of each line, e.g. "\n" or "\n"
165 * firstline printed before first line, e.g. NULL or "<!--+\n"
166 * lastline printed after last line, e.g. "\n" or " +-->\n"
170 print_version_comment(FILE *out,
171 const char *startline, const char *endline,
172 const char *firstline, const char *lastline)
175 if (out == NULL) { FATAL("Internal error: NULL out in print_version_comment()"); }
176 if (firstline != NULL) { fputs(firstline, out); }
177 fputs(startline, out);
178 fputs("Created from this library:", out);
180 for (n=0; (module_versions[n].name != NULL) && (module_versions[n].version_func != NULL); n++) {
181 const char *name = module_versions[n].name;
182 GPVersionFunc func = module_versions[n].version_func;
183 const char **v = func(GP_VERSION_SHORT);
185 if (!v) { continue; }
186 if (!v[0]) { continue; }
187 if (startline != NULL) { fputs(startline, out); }
189 fprintf(out,"%-15s %-14s ", name, v[0]);
190 for (i=1; v[i] != NULL; i++) {
192 if (v[i+1] != NULL) {
196 if (endline != NULL) { fputs(endline, out); }
198 if (lastline != NULL) { fputs(lastline, out); }
203 hotplug_begin_func (const func_params_t *params, void **data)
205 if (params->add_comments) {
206 printf("# linux-hotplug configuration file "
207 "for libgphoto2 supported devices\n");
208 print_version_comment(stdout, "# ", "\n", NULL, "#\n");
216 * Print out lines that can be included into usb.usermap
217 * - for all cams supported by our instance of libgphoto2.
219 * usb.usermap is a file used by
220 * Linux Hotplug http://linux-hotplug.sourceforge.net/
224 hotplug_camera_func (const func_params_t *params,
227 const CameraAbilities *a,
231 int class = 0, subclass = 0, proto = 0;
232 int usb_vendor = 0, usb_product = 0;
233 const char *usermap_script =
234 ((*params->argv)[0] != NULL)
235 ?((*params->argv)[0])
236 :(GP_USB_HOTPLUG_SCRIPT);
238 if (a->port & GP_PORT_USB) {
239 if (a->usb_vendor) { /* usb product id may be zero! */
243 flags = (GP_USB_HOTPLUG_MATCH_VENDOR_ID
244 | GP_USB_HOTPLUG_MATCH_PRODUCT_ID);
245 usb_vendor = a->usb_vendor;
246 usb_product = a->usb_product;
247 } else if ((a->usb_class) && (a->usb_class != 666)) {
248 class = a->usb_class;
249 subclass = a->usb_subclass;
250 proto = a->usb_protocol;
251 flags = GP_USB_HOTPLUG_MATCH_INT_CLASS;
253 flags |= GP_USB_HOTPLUG_MATCH_INT_SUBCLASS;
257 flags |= GP_USB_HOTPLUG_MATCH_INT_PROTOCOL;
264 /* not a USB camera */
268 if (params->add_comments) {
272 /* The first 3 lone bytes are the device class.
273 * the second 3 lone bytes are the interface class.
274 * for PTP we want the interface class.
277 "0x%04x 0x%04x 0x%04x 0x0000 "
279 "0x00 0x%02x 0x%02x "
280 "0x%02x 0x00000000\n",
281 usermap_script, flags,
282 a->usb_vendor, a->usb_product,
283 class, subclass, proto);
289 print_headline (void)
291 printf("No.|%-20s|%-20s|%s\n",
301 printf("---+%-20s+%-20s+%s\n",
302 "--------------------",
303 "--------------------",
304 "-------------------------------------------");
309 human_begin_func (const func_params_t *params, void **data)
319 human_end_func (const func_params_t *params, void *data)
327 /** C equivalent of basename(1) */
329 path_basename (const char *pathname)
332 /* remove path part from camlib name */
333 for (result=tmp=(char *)pathname; (*tmp!='\0'); tmp++) {
334 if ((*tmp == gp_system_dir_delim)
335 && (*(tmp+1) != '\0')) {
339 return (const char *)result;
344 human_camera_func (const func_params_t *params,
347 const CameraAbilities *a,
350 const char *camlib_basename;
351 camlib_basename = path_basename(a->library);
352 printf("%3d|%-20s|%-20s|%s\n",
362 idlist_camera_func (const func_params_t *params,
365 const CameraAbilities *a,
368 if (a->usb_vendor) { /* usb product id may be zero! */
369 printf("%04x:%04x %s\n",
384 static const StringFlagItem udev_version_t_map[] = {
385 { "pre-0.98", UDEV_PRE_0_98 },
386 { "0.98", UDEV_0_98 },
393 udev_version_t version;
398 const char *begin_string;
399 const char *usbcam_string;
400 const char *usbdisk_string;
401 } udev_persistent_data_t;
405 udev_parse_params (const func_params_t *params, void **data)
407 /* Note: 2 lines because we need to use || ... having them on the same
408 * line would mean &&.
410 static const char * const begin_strings[] = {
412 "ACTION!=\"add\", GOTO=\"libgphoto2_rules_end\"\n"
413 "BUS!=\"usb_device\", GOTO=\"libgphoto2_usb_end\"\n\n",
415 "ACTION!=\"add\", GOTO=\"libgphoto2_rules_end\"\n"
416 "SUBSYSTEM!=\"usb|usb_device\", GOTO=\"libgphoto2_usb_end\"\n\n",
418 "ACTION!=\"add\", GOTO=\"libgphoto2_rules_end\"\n"
419 "SUBSYSTEM!=\"usb\", GOTO=\"libgphoto2_usb_end\"\n"
420 "ENV{DEVTYPE}!=\"usb_device\", GOTO=\"libgphoto2_usb_end\"\n\n"
421 "ENV{ID_USB_INTERFACES}==\"\", IMPORT{program}=\"usb_id --export %%p\"\n"
422 /* ignore mass storage class having devices in mark-up */
423 "ENV{ID_USB_INTERFACES}==\"*:08*:*\", GOTO=\"libgphoto2_usb_end\"\n"
424 /* shortcut the most common camera driver, ptp class, so we avoid parsing 1000
425 * more rules . It will be completed in udev_begin_func() */
426 "ENV{ID_USB_INTERFACES}==\"*:060101:*\", ENV{ID_GPHOTO2}=\"1\", ENV{GPHOTO2_DRIVER}=\"PTP\", "
428 static const char * const usbcam_strings[] = {
430 "SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\"",
432 "ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\"",
434 "ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{ID_GPHOTO2}=\"1\", ENV{GPHOTO2_DRIVER}=\"proprietary\""
436 static const char * const usbdisk_strings[] = {
438 "KERNEL==\"%s\", SYSFS{idVendor}==\"%04x\", SYSFS{idProduct}==\"%04x\"",
440 "KERNEL==\"%s\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\"",
442 "KERNEL==\"%s\", ATTRS{idVendor}==\"%04x\", ATTRS{idProduct}==\"%04x\", ENV{ID_GPHOTO2}=\"1\", ENV{GPHOTO2_DRIVER}=\"proprietary\""
444 udev_persistent_data_t *pdata;
445 pdata = calloc(1, sizeof(udev_persistent_data_t));
446 pdata->version = UDEV_0_98;
447 ASSERT(data != NULL);
448 *data = (void *) pdata;
451 char *key = NULL, *val = NULL;
452 for (i=0; ((key=(*params->argv)[i]) != NULL) &&
453 ((val=(*params->argv)[i+1]) != NULL); i+=2) {
456 } else if (strcmp("script", key)==0) {
458 } else if (strcmp("owner", key)==0) {
460 } else if (strcmp("group", key)==0) {
462 } else if (strcmp("version", key)==0) {
463 unsigned int *ver = &pdata->version;
464 if (gpi_string_to_enum(val, ver,
465 udev_version_t_map)) {
466 FATAL("Unrecognized udev version: \"%s\"", val);
468 } else if (strcmp("mode", key)==0) {
471 FATAL("Unknown key argument: %s", key);
474 if ((key != NULL) && (val == NULL)) {
475 FATAL("Single argument remaining; need pairs of key and value");
479 && (pdata->mode == NULL)
480 && (pdata->group == NULL)
481 && (pdata->owner == NULL)
482 && (pdata->script == NULL)
483 && (pdata->version <= UDEV_0_98)) {
484 FATAL("Either <script> or <mode,group,owner> parameters must be given.");
486 if ((pdata->script != NULL) && (pdata->mode != NULL
487 || pdata->group != NULL
488 || pdata->owner != NULL)) {
489 FATAL("The <script> parameter conflicts with the <mode,group,owner> parameters.");
492 pdata->begin_string = begin_strings[pdata->version];
493 pdata->usbcam_string = usbcam_strings[pdata->version];
494 pdata->usbdisk_string = usbdisk_strings[pdata->version];
499 get_version_str(udev_version_t version)
501 return gpi_enum_to_string(version, udev_version_t_map);
506 udev_begin_func (const func_params_t *params, void **data)
508 udev_parse_params(params, data);
510 udev_persistent_data_t *pdata = (udev_persistent_data_t *) (*data);
511 const char *version_str = get_version_str(pdata->version);
512 ASSERT(pdata != NULL);
513 ASSERT(version_str != NULL);
514 printf ("# udev rules file for libgphoto2 devices (for udev %s version)\n",
516 print_version_comment(stdout, "# ", "\n", NULL, "#\n");
517 printf ("# this file is autogenerated, local changes will be LOST on upgrades\n");
518 printf (pdata->begin_string);
520 if (pdata->version == UDEV_136) {
521 if (pdata->mode != NULL || pdata->owner != NULL || pdata->group != NULL) {
522 if (pdata->mode != NULL) {
523 printf("MODE=\"%s\", ", pdata->mode);
525 if (pdata->owner != NULL) {
526 printf("OWNER=\"%s\", ", pdata->owner);
528 if (pdata->group != NULL) {
529 printf("GROUP=\"%s\", ", pdata->group);
533 printf ("GOTO=\"libgphoto2_usb_end\"\n\n");
541 udev_middle_func (const func_params_t *params, void **data)
543 printf ("\nLABEL=\"libgphoto2_usb_end\"\n\n");
549 udev_end_func (const func_params_t *params, void *data)
555 #ifdef _GPHOTO2_SAMSUNG_PATCH_
557 printf ("ENV{ID_GPHOTO2}==\"1\", RUN+=\"%s %s\"\n",
558 RM_CMD, CAMERA_NAME_INFO_PATH);
559 printf ("ENV{ID_GPHOTO2}==\"1\", RUN+=\"%s %s\"\n",
560 MKDIR_CMD, CAMERA_NAME_INFO_PATH);
561 printf ("ENV{ID_GPHOTO2}==\"1\", RUN+=\"%s %s/$env{ID_MODEL}\"\n",
562 TOUCH_CMD, CAMERA_NAME_INFO_PATH);
563 printf ("ENV{ID_GPHOTO2}==\"1\", RUN+=\"%s %s\"\n",
564 SYS_EVENT_PATH, SYS_CAMERA_ADD_EVENT);
566 printf ("\nLABEL=\"libgphoto2_rules_end\"\n");
568 printf ("ACTION==\"remove\", ENV{DEVTYPE}==\"usb_interface\", ENV{INTERFACE}==\"6/[0-9]/[0-9]\", RUN+=\"%s %s\"\n",
569 RM_CMD, CAMERA_NAME_INFO_PATH);
570 printf ("ACTION==\"remove\", ENV{DEVTYPE}==\"usb_interface\", ENV{INTERFACE}==\"6/[0-9]/[0-9]\", RUN+=\"%s %s\"\n",
571 SYS_EVENT_PATH, SYS_CAMERA_REMOVE_EVENT);
575 printf ("\nLABEL=\"libgphoto2_rules_end\"\n");
583 udev_camera_func (const func_params_t *params,
586 const CameraAbilities *a,
590 int class = 0, subclass = 0, proto = 0;
591 int usb_vendor = 0, usb_product = 0;
592 int has_valid_rule = 0;
593 udev_persistent_data_t *pdata = (udev_persistent_data_t *) data;
594 ASSERT(pdata != NULL);
596 if (!(a->port & GP_PORT_USB))
599 if (a->usb_vendor) { /* usb product id may be zero! */
603 flags = (GP_USB_HOTPLUG_MATCH_VENDOR_ID
604 | GP_USB_HOTPLUG_MATCH_PRODUCT_ID);
605 usb_vendor = a->usb_vendor;
606 usb_product = a->usb_product;
609 class = a->usb_class;
610 subclass = a->usb_subclass;
611 proto = a->usb_protocol;
612 flags = GP_USB_HOTPLUG_MATCH_INT_CLASS;
614 flags |= GP_USB_HOTPLUG_MATCH_INT_SUBCLASS;
618 flags |= GP_USB_HOTPLUG_MATCH_INT_PROTOCOL;
626 if (params->add_comments) {
627 printf ("# %s\n", a->model);
630 if (flags & GP_USB_HOTPLUG_MATCH_INT_CLASS) {
631 if ((flags & (GP_USB_HOTPLUG_MATCH_INT_CLASS|GP_USB_HOTPLUG_MATCH_INT_SUBCLASS|GP_USB_HOTPLUG_MATCH_INT_PROTOCOL)) == (GP_USB_HOTPLUG_MATCH_INT_CLASS|GP_USB_HOTPLUG_MATCH_INT_SUBCLASS|GP_USB_HOTPLUG_MATCH_INT_PROTOCOL)) {
632 if (pdata->version == UDEV_136) {
633 printf("ENV{ID_USB_INTERFACES}==\"*:%02d%02d%02d:*\", ENV{ID_GPHOTO2}=\"1\", ENV{GPHOTO2_DRIVER}=\"PTP\"", class, subclass, proto);
635 printf("PROGRAM=\"check-ptp-camera %02d/%02d/%02d\"", class, subclass, proto);
640 printf("# not working yet: PROGRAM=\"check-mtp-device\", ");
643 fprintf(stderr, "unhandled interface match flags %x\n", flags);
647 if (flags & GP_USB_HOTPLUG_MATCH_VENDOR_ID) {
648 printf (pdata->usbcam_string, a->usb_vendor, a->usb_product);
651 fprintf (stderr, "Error: Trying to output device %d/%d with incorrect match flags.\n",
652 a->usb_vendor, a->usb_product
656 if (has_valid_rule != 0) {
657 if (a->device_type & GP_DEVICE_AUDIO_PLAYER)
658 printf(", ENV{ID_MEDIA_PLAYER}=\"1\"");
660 if (pdata->script != NULL || pdata->mode != NULL || pdata->owner != NULL || pdata->group != NULL)
663 if (pdata->script != NULL) {
664 printf("RUN+=\"%s\"\n", pdata->script);
665 } else if (pdata->mode != NULL || pdata->owner != NULL || pdata->group != NULL) {
666 if (pdata->mode != NULL) {
667 printf("MODE=\"%s\"", pdata->mode);
668 if (pdata->owner != NULL || pdata->group != NULL) {
672 if (pdata->owner != NULL) {
673 printf("OWNER=\"%s\"", pdata->owner);
674 if (pdata->group != NULL) {
678 if (pdata->group != NULL) {
679 printf("GROUP=\"%s\"", pdata->group);
684 if (pdata->version < UDEV_136)
685 FATAL("udev_camera_func(): illegal branch");
693 udev_camera_func2 (const func_params_t *params,
696 const CameraAbilities *a,
699 int has_valid_rule = 0;
700 udev_persistent_data_t *pdata = (udev_persistent_data_t *) data;
701 ASSERT(pdata != NULL);
703 if (a->port & GP_PORT_USB_DISK_DIRECT) {
704 printf (pdata->usbdisk_string, "sd[a-z]*",
705 a->usb_vendor, a->usb_product);
708 if (a->port & GP_PORT_USB_SCSI) {
709 printf (pdata->usbdisk_string, "sg[0-9]*",
710 a->usb_vendor, a->usb_product);
713 if (has_valid_rule != 0) {
714 if (pdata->script != NULL || pdata->mode != NULL || pdata->owner != NULL || pdata->group != NULL)
717 if (pdata->script != NULL) {
718 printf("RUN+=\"%s\"\n", pdata->script);
719 } else if (pdata->mode != NULL || pdata->owner != NULL || pdata->group != NULL) {
720 if (pdata->mode != NULL) {
721 printf("MODE=\"%s\"", pdata->mode);
722 if (pdata->owner != NULL || pdata->group != NULL) {
726 if (pdata->owner != NULL) {
727 printf("OWNER=\"%s\"", pdata->owner);
728 if (pdata->group != NULL) {
732 if (pdata->group != NULL) {
733 printf("GROUP=\"%s\"", pdata->group);
738 if (pdata->version < UDEV_136)
739 FATAL("udev_camera_func(): illegal branch");
748 empty_begin_func (const func_params_t *params, void **data)
754 empty_end_func (const func_params_t *params, void *data)
761 #ifdef ENABLED_GP2DDB
764 ddb_begin_func (const func_params_t *params, void **data)
766 printf("# Beginning of gphoto2 device database (PRE-ALPHA format!)\n\n");
767 print_version_comment(stdout, "# ", "\n", NULL, "\n");
773 ddb_end_func (const func_params_t *params, void *data)
775 printf("# End of gphoto2 device database (PRE-ALPHA format!).\n");
781 ddb_list_out_func(const char *str, void *data)
783 int *first = (int *)data;
784 printf("%s %s", (*first)?"":",", str);
790 ddb_delayed_head(const func_params_t *params,
793 const CameraAbilities *a,
794 const char *camlib_basename)
797 printf("# This is a PRE-ALPHA data format. Do not use it.\n\n");
799 if (params->add_comments) {
800 printf ("# %s\n", a->model);
803 printf("# automatically generated camera record %d/%d\n", i+1, total);
804 printf("device \"%s\" {\n", a->model);
806 printf(" device_type");
808 gpi_enum_to_string(a->device_type,
809 gpi_gphoto_device_type_map,
814 printf(" driver \"%s\";\n", camlib_basename);
816 printf(" driver_status");
818 gpi_enum_to_string(a->status,
819 gpi_camera_driver_status_map,
824 printf(" operations");
826 gpi_flags_to_string_list(a->operations,
827 gpi_camera_operation_map,
832 printf(" file_operations");
834 gpi_flags_to_string_list(a->file_operations,
835 gpi_file_operation_map,
840 printf(" folder_operations");
842 gpi_flags_to_string_list(a->folder_operations,
843 gpi_folder_operation_map,
851 ddb_camera_func (const func_params_t *params,
854 const CameraAbilities *a,
857 const char *camlib_basename = path_basename(a->library);
858 int head_printed = 0;
859 #define DELAYED_HEAD() \
861 if (!head_printed) { \
862 ddb_delayed_head(params, i, total, \
863 a, camlib_basename); \
868 if ((a->port & GP_PORT_SERIAL)) {
871 printf(" interface serial {\n");
872 if (a->speed[0] != 0) {
876 ((i < (sizeof(a->speed)/sizeof(a->speed[0]))) &&
877 (a->speed[i] != 0)); i++) {
878 printf("%s %d", (first)?"":",", a->speed[i]);
886 if ((a->port & GP_PORT_USB)) {
888 /* usb product id may have the legal value zero! */
890 printf(" interface usb {\n");
891 printf(" vendor 0x%04x;\n", a->usb_vendor);
892 printf(" product 0x%04x;\n", a->usb_product);
895 if ((a->usb_class) && (a->usb_class != 666)) {
897 printf(" interface usb {\n");
898 printf(" class 0x%02x;\n", a->usb_class);
899 if (a->usb_subclass != -1) {
900 printf(" subclass 0x%02x;\n", a->usb_subclass);
902 if (a->usb_protocol != -1) {
903 printf(" protocol 0x%02x;\n", a->usb_protocol);
908 if ((a->port & GP_PORT_DISK)) {
910 printf(" interface disk;\n");
912 if ((a->port & GP_PORT_PTPIP)) {
914 printf(" interface ptpip;\n");
919 printf(" # driver_options {\n");
920 printf(" # option \"foo\";\n");
921 printf(" # option \"bar\" \"bla\";\n");
924 printf("}; # %s\n\n", a->model);
929 #endif /* ENABLED_GP2DDB */
934 * Print FDI Device Information file for HAL with information on
935 * all cams supported by our instance of libgphoto2.
937 * For specs, look around on http://freedesktop.org/ and search
938 * for FDI on the HAL pages.
942 fdi_begin_func (const func_params_t *params, void **data)
944 printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- -->\n");
945 printf("<!-- This file was generated by %s - - fdi -->\n",
946 "libgphoto2 " ARGV0);
947 print_version_comment(stdout, " | ", "\n", "<!--+\n", " +-->\n");
948 printf("<deviceinfo version=\"0.2\">\n");
949 printf(" <device>\n");
950 printf(" <match key=\"info.subsystem\" string=\"usb\">\n");
956 fdi_camera_func (const func_params_t *params,
959 const CameraAbilities *a,
962 char *s, *d, model[256];
964 if (!(a->port & GP_PORT_USB))
967 s = (char *) a->model;
969 while (*s && (d < &d[sizeof(d)-1])) {
980 if ((a->port & GP_PORT_USB)) {
981 if (a->usb_vendor == 0x07b4 && (a->usb_product == 0x105 || a->usb_product == 0x109) ) {
982 /* Marcus says: The Olympus Sierra/Storage dual mode camera firmware.
983 * Some HAL using software gets deeply confused by this being here
984 * and also detected as mass storage elsewhere, so blacklist
989 if (a->usb_vendor) { /* usb product id might be 0! */
990 printf(" <match key=\"usb.vendor_id\" int=\"%d\">\n", a->usb_vendor);
991 printf(" <match key=\"usb.product_id\" int=\"%d\">\n", a->usb_product);
992 if (a->usb_vendor == 0x05ac) { /* Apple iPhone, PTP user. */
993 printf(" <match key=\"usb.interface.class\" int=\"6\">\n");
994 printf(" <match key=\"usb.interface.subclass\" int=\"1\">\n");
995 printf(" <match key=\"usb.interface.protocol\" int=\"1\">\n");
997 if (a->device_type & GP_DEVICE_AUDIO_PLAYER) {
998 printf(" <merge key=\"info.category\" type=\"string\">portable_audio_player</merge>\n");
999 printf(" <addset key=\"info.capabilities\" type=\"strlist\">portable_audio_player</addset>\n");
1000 printf(" <merge key=\"portable_audio_player.access_method\" type=\"string\">user</merge>\n");
1001 printf(" <merge key=\"portable_audio_player.type\" type=\"string\">mtp</merge>\n");
1003 /* FIXME: needs true formats ... But all of them can do MP3 */
1004 printf(" <append key=\"portable_audio_player.output_formats\" type=\"strlist\">audio/mpeg</append>\n");
1006 printf(" <merge key=\"info.category\" type=\"string\">camera</merge>\n");
1007 printf(" <addset key=\"info.capabilities\" type=\"strlist\">camera</addset>\n");
1009 /* HACK alert ... but the HAL / gnome-volume-manager guys want that */
1010 if (NULL!=strstr(a->library,"ptp"))
1011 printf(" <merge key=\"camera.access_method\" type=\"string\">ptp</merge>\n");
1013 printf(" <merge key=\"camera.access_method\" type=\"string\">proprietary</merge>\n");
1015 /* leave them here even for audio players */
1016 printf(" <merge key=\"camera.libgphoto2.name\" type=\"string\">%s</merge>\n", model);
1017 printf(" <merge key=\"camera.libgphoto2.support\" type=\"bool\">true</merge>\n");
1018 if (a->usb_vendor == 0x05ac) { /* Apple iPhone */
1019 printf(" </match>\n");
1020 printf(" </match>\n");
1021 printf(" </match>\n");
1023 printf(" </match>\n");
1024 printf(" </match>\n");
1026 } else if ((a->usb_class) && (a->usb_class != 666)) {
1027 printf(" <match key=\"usb.interface.class\" int=\"%d\">\n", a->usb_class);
1028 printf(" <match key=\"usb.interface.subclass\" int=\"%d\">\n", a->usb_subclass);
1029 printf(" <match key=\"usb.interface.protocol\" int=\"%d\">\n", a->usb_protocol);
1030 printf(" <merge key=\"info.category\" type=\"string\">camera</merge>\n");
1031 printf(" <addset key=\"info.capabilities\" type=\"strlist\">camera</addset>\n");
1032 if (a->usb_class == 6) {
1033 printf(" <merge key=\"camera.access_method\" type=\"string\">ptp</merge>\n");
1035 if (a->usb_class == 8) {
1036 printf(" <merge key=\"camera.access_method\" type=\"string\">storage</merge>\n");
1038 printf(" <merge key=\"camera.access_method\" type=\"string\">proprietary</merge>\n");
1041 printf(" <merge key=\"camera.libgphoto2.name\" type=\"string\">%s</merge>\n", model);
1042 printf(" <merge key=\"camera.libgphoto2.support\" type=\"bool\">true</merge>\n");
1043 printf(" </match>\n");
1044 printf(" </match>\n");
1045 printf(" </match>\n");
1047 } /* camera has USB connection */
1052 fdi_end_func (const func_params_t *params, void *data)
1054 printf(" </match>\n");
1055 printf(" </device>\n");
1056 printf("</deviceinfo>\n");
1061 /* print_fdi_device_map
1063 * Print FDI Device Information file for HAL with information on
1064 * all cams supported by our instance of libgphoto2.
1066 * For specs, look around on http://freedesktop.org/ and search
1067 * for FDI on the HAL pages.
1071 fdi_device_begin_func (const func_params_t *params, void **data)
1073 printf("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?> <!-- -*- SGML -*- -->\n");
1074 printf("<!-- This file was generated by %s - - fdi-device -->\n",
1075 "libgphoto2 " ARGV0);
1076 print_version_comment(stdout, " | ", "\n", "<!--+\n", " +-->\n");
1077 printf("<deviceinfo version=\"0.2\">\n");
1078 printf(" <device>\n");
1079 printf(" <match key=\"info.subsystem\" string=\"usb\">\n");
1085 fdi_device_camera_func (const func_params_t *params,
1088 const CameraAbilities *a,
1091 char *s, *d, model[256];
1093 if (!(a->port & GP_PORT_USB))
1096 s = (char *) a->model;
1098 while (*s && (d < &d[sizeof(d)-1])) {
1109 if ((a->port & GP_PORT_USB)) {
1111 if (a->usb_vendor == 0x07b4 && (a->usb_product == 0x105 || a->usb_product == 0x109)) {
1112 /* Marcus says: The Olympus Sierra/Storage dual mode camera firmware.
1113 * Some HAL using software gets deeply confused by this being here
1114 * and also detected as mass storage elsewhere, so blacklist
1119 if (a->usb_vendor) { /* usb product id might be 0! */
1120 /* do not set category. We don't really know what this device really is.
1121 * But we do now that is capable of being a camera, so add to capabilities
1123 printf(" <match key=\"usb_device.vendor_id\" int=\"%d\">\n", a->usb_vendor);
1124 printf(" <match key=\"usb_device.product_id\" int=\"%d\">\n", a->usb_product);
1125 if (params->add_comments) {
1126 printf(" <!-- %s -->\n", a->model);
1128 if (a->device_type & GP_DEVICE_AUDIO_PLAYER)
1129 printf(" <append key=\"info.capabilities\" type=\"strlist\">portable_audio_player</append>\n");
1131 printf(" <append key=\"info.capabilities\" type=\"strlist\">camera</append>\n");
1132 printf(" </match>\n");
1133 printf(" </match>\n");
1136 /* would need to be able to merge upwards ... but cannot currently */
1137 else if ((a->usb_class) && (a->usb_class != 666)) {
1138 printf(" <match key=\"usb.interface.class\" int=\"%d\">\n", a->usb_class);
1139 printf(" <match key=\"usb.interface.subclass\" int=\"%d\">\n", a->usb_subclass);
1140 printf(" <match key=\"usb.interface.protocol\" int=\"%d\">\n", a->usb_protocol);
1141 printf(" <append key=\"info.capabilities\" type=\"strlist\">camera</append>\n");
1142 printf(" </match>\n");
1143 printf(" </match>\n");
1144 printf(" </match>\n");
1152 fdi_device_end_func (const func_params_t *params, void *data)
1154 printf(" </match>\n");
1155 printf(" </device>\n");
1156 printf("</deviceinfo>\n");
1161 /* time zero for debug log time stamps */
1162 struct timeval glob_tv_zero = { 0, 0 };
1165 debug_func (GPLogLevel level, const char *domain, const char *format,
1166 va_list args, void *data)
1169 gettimeofday (&tv,NULL);
1170 fprintf (stderr, "%li.%06li %s(%i): ",
1171 tv.tv_sec - glob_tv_zero.tv_sec,
1172 (1000000 + tv.tv_usec - glob_tv_zero.tv_usec) % 1000000,
1174 vfprintf (stderr, format, args);
1175 fprintf (stderr, "\n");
1184 begin_func_t begin_func;
1185 camera_func_t camera_func;
1186 middle_func_t middle_func;
1187 camera_func_t camera_func2;
1188 end_func_t end_func;
1193 iterate_camera_list (const int add_comments,
1194 const output_format_t *format,
1195 string_array_p argv)
1197 int number_of_cameras;
1198 CameraAbilitiesList *al;
1200 func_params_t params;
1204 CR (gp_abilities_list_new (&al));
1205 ret = gp_abilities_list_load (al, NULL); /* use NULL context */
1207 gp_abilities_list_free (al);
1210 number_of_cameras = gp_abilities_list_count (al);
1211 if (number_of_cameras < GP_OK) {
1212 gp_abilities_list_free (al);
1216 params.add_comments = add_comments;
1217 params.number_of_cameras = number_of_cameras;
1220 if (format->begin_func != NULL) {
1221 format->begin_func(¶ms, &data);
1224 if (format->camera_func != NULL) {
1226 for (i = 0; i < number_of_cameras; i++) {
1227 ret = gp_abilities_list_get_abilities (al, i, &a);
1230 format->camera_func(¶ms, i, number_of_cameras, &a, data);
1234 if (format->middle_func != NULL) {
1235 format->middle_func(¶ms, &data);
1238 if (format->camera_func2 != NULL) {
1240 for (i = 0; i < number_of_cameras; i++) {
1241 ret = gp_abilities_list_get_abilities (al, i, &a);
1244 format->camera_func2(¶ms, i, number_of_cameras, &a, data);
1248 if (format->end_func != NULL) {
1249 format->end_func(¶ms, data);
1251 CR (gp_abilities_list_free (al));
1256 /* FIXME: Add hyperlink to format documentation. */
1258 /** list of supported output formats */
1259 static const output_format_t formats[] = {
1261 "human readable list of cameras",
1271 "usb.usermap include file for linux-hotplug",
1272 "If no <scriptname> is given, uses the script name "
1273 "\"" GP_USB_HOTPLUG_SCRIPT "\".\n"
1274 " Put this into /etc/hotplug/usb/<scriptname>.usermap",
1275 "<NAME_OF_HOTPLUG_SCRIPT>",
1277 hotplug_camera_func,
1284 "Put it into /usr/share/hal/fdi/information/20thirdparty/10-camera-libgphoto2.fdi",
1293 "fdi device file for HAL",
1294 "Put it into /usr/share/hal/fdi/information/20thirdparty/10-camera-libgphoto2-device.fdi",
1296 fdi_device_begin_func,
1297 fdi_device_camera_func,
1304 "For modes \"pre-0.98\" and \"0.98\" (and later), put it into\n"
1305 " /etc/udev/rules.d/90-libgphoto2.rules, set file mode, owner, group\n"
1306 " or add script to run. This rule files also uses the\n"
1307 " check-ptp-camera script included in libgphoto2 source. Either put it to\n"
1308 " /lib/udev/check-ptp-camera or adjust the path in the generated rules file.\n"
1309 " If you give a script parameter, the mode, owner, group parameters will be ignored.\n"
1310 " For mode \"136\" put it into /lib/udev/rules.d/40-libgphoto2.rules;\n"
1311 " you can still use mode/owner/group, but the preferred mode of operation\n"
1312 " is to use udev-extras for dynamic access permissions.\n",
1313 "[script <PATH_TO_SCRIPT>|version <version>|mode <mode>|owner <owner>|group <group>]*",
1321 "list of IDs and names",
1322 "grep for an ID to find the device name",
1330 #ifdef ENABLED_GP2DDB
1332 "gphoto2 device database (PRE-ALPHA)",
1333 "PRE-ALPHA test stage, do not use for production! Machine parseable.",
1342 {NULL, NULL, NULL, NULL,
1347 /** \brief print list of output formats with descriptions
1350 static int print_format_list(const output_format_t *formats)
1353 printf("List of output formats:\n");
1354 for (i=0; formats[i].name != NULL; ++i) {
1355 if (formats[i].paramdescr != NULL) {
1356 printf(" %s %s\n %s\n",
1358 formats[i].paramdescr,
1361 printf(" %s\n %s\n",
1362 formats[i].name, formats[i].descr);
1364 if (formats[i].help != NULL) {
1365 printf(" %s\n", formats[i].help);
1372 /** \brief print program help
1375 static int print_help()
1378 return print_format_list(formats);
1382 /** \brief main program: parse and check arguments, then delegate the work
1385 int main(int argc, char *argv[])
1387 int add_comments = FALSE; /* whether to add cam model as a comment */
1388 int debug_mode = FALSE; /* whether we should output debug messages */
1390 char *format_name = NULL; /* name of desired output format */
1391 int format_index; /* index number of (desired) output format */
1392 static char *fmt_argv[16]; /* format specific arguments */
1397 /* initialize parameters to NULL */
1398 for (ui=0; ui<(sizeof(fmt_argv)/sizeof(fmt_argv[0])); ui++) {
1399 fmt_argv[ui] = NULL;
1402 /* walk through command line arguments until format is encountered */
1403 for (i=1; (i<argc) && (format_name == NULL); i++) {
1404 if (0 == strcmp(argv[i], "--verbose")) {
1406 fprintf(stderr, "Error: duplicate parameter: option \"%s\"\n", argv[i]);
1409 add_comments = TRUE;
1410 } else if (0 == strcmp(argv[i], "--debug")) {
1412 fprintf(stderr, "Error: duplicate parameter: option \"%s\"\n", argv[i]);
1416 /* now is time zero for debug log time stamps */
1417 gettimeofday (&glob_tv_zero, NULL);
1418 gp_log_add_func (GP_LOG_ALL, debug_func, NULL);
1419 } else if (0 == strcmp(argv[i], "--help")) {
1420 return print_help();
1422 format_name = argv[i];
1426 /* walk through output format list, searching for the requested one */
1427 if (format_name == NULL) {
1428 return print_help();
1431 while (formats[format_index].name != NULL) {
1432 if (strcmp(formats[format_index].name, format_name) == 0) {
1437 if ((formats[format_index].name == NULL) ||
1438 (strcmp(formats[format_index].name, format_name) != 0)) {
1439 return print_help();
1442 /* copy remaining arguments */
1444 (j<argc) && ((j-i)<(int)((sizeof(fmt_argv)/sizeof(fmt_argv[0]))-1));
1446 fmt_argv[j-i] = argv[j];
1449 /* execute the work using the given parameters*/
1450 return iterate_camera_list(add_comments, &formats[format_index],
1457 * c-file-style:"linux"
1458 * indent-tabs-mode:t