00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <ctype.h>
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <getopt.h>
00035 #include <assert.h>
00036 #include <unistd.h>
00037 #include <stdarg.h>
00038
00039 #include <glib.h>
00040
00041 #include "../logger.h"
00042 #include "../device_store.h"
00043 #include "linux_class_v4l.h"
00044
00052
00053 static void visit_class_device_v4l_got_sysdevice (HalDevice * parent,
00054 void *data1,
00055 void *data2);
00056
00065 void
00066 visit_class_device_v4l (const char *path,
00067 struct sysfs_class_device *class_device)
00068 {
00069 HalDevice *d;
00070 struct sysfs_attribute *cur;
00071 char *sysdevice_sysfs_path;
00072 char *product_name = NULL;
00073 char attr_name[SYSFS_NAME_LEN];
00074 char v4l_class[32];
00075 const char *last_elem;
00076 int adapter_num;
00077 int len;
00078 int i;
00079 char buf[256];
00080 char dev_file[256];
00081
00082 if (class_device->sysdevice == NULL) {
00083 HAL_INFO (("Skipping virtual class device at path %s\n",
00084 path));
00085 return;
00086 }
00087
00088 HAL_INFO (("v4l: sysdevice_path=%s, path=%s\n",
00089 class_device->sysdevice->path, path));
00090
00093
00094 last_elem = get_last_element (path);
00095 sscanf (last_elem, "%32[a-z]%d", v4l_class, &adapter_num);
00096
00097
00098 dlist_for_each_data (sysfs_get_classdev_attributes (class_device),
00099 cur, struct sysfs_attribute) {
00100 if (sysfs_get_name_from_path
00101 (cur->path, attr_name, SYSFS_NAME_LEN) != 0)
00102 continue;
00103
00104
00105 len = strlen (cur->value);
00106 for (i = len - 1; isspace (cur->value[i]); --i)
00107 cur->value[i] = '\0';
00108
00109
00110
00111 if (strcmp (attr_name, "name") == 0)
00112 product_name = cur->value;
00113 }
00114
00115
00116
00117 dev_file[0] = '\0';
00118 if (is_probing) {
00119 int i;
00120 int sysfs_mount_path_len;
00121 char sysfs_path_trunc[SYSFS_NAME_LEN];
00122 char *udev_argv[7] =
00123 { udevinfo_path (), "-r", "-q", "name", "-p",
00124 sysfs_path_trunc, NULL
00125 };
00126 char *udev_stdout;
00127 char *udev_stderr;
00128 int udev_exitcode;
00129
00130
00131 sysfs_mount_path_len = strlen (sysfs_mount_path);
00132 if (strlen (path) > sysfs_mount_path_len) {
00133 strncpy (sysfs_path_trunc,
00134 path + sysfs_mount_path_len,
00135 SYSFS_NAME_LEN);
00136 }
00137 HAL_INFO (("*** sysfs_path_trunc = '%s'",
00138 sysfs_path_trunc));
00139
00140
00141 if (udev_argv[0] == NULL || g_spawn_sync ("/",
00142 udev_argv,
00143 NULL,
00144 0,
00145 NULL,
00146 NULL,
00147 &udev_stdout,
00148 &udev_stderr,
00149 &udev_exitcode,
00150 NULL) != TRUE) {
00151 HAL_ERROR (("Couldn't invoke udevinfo"));
00152 goto error;
00153 }
00154
00155 if (udev_exitcode != 0) {
00156 HAL_ERROR (("udevinfo returned %d",
00157 udev_exitcode));
00158 goto error;
00159 }
00160
00161
00162 for (i = 0; udev_stdout[i] != 0; i++) {
00163 if (udev_stdout[i] == '\r'
00164 || udev_stdout[i] == '\n') {
00165 udev_stdout[i] = 0;
00166 break;
00167 }
00168 }
00169
00170 strncat (dev_file, udev_stdout, 256);
00171
00173 } else {
00174 error:
00175 }
00176
00177 HAL_INFO (("device file = '%s'", dev_file));
00178
00179 d = ds_device_new ();
00180 ds_add_capability (d, "v4l");
00181 ds_property_set_string (d, "info.category", "v4l");
00182 if (strcmp (v4l_class, "vbi") == 0) {
00183 ds_property_set_string (d, "v4l.vbi.linux.sysfs_path",
00184 path);
00185 ds_property_set_int (d, "v4l.vbi.adapter", adapter_num);
00186 ds_property_set_string (d, "v4l.vbi.device", dev_file);
00187
00188 if (product_name == NULL)
00189 ds_property_set_string (d, "v4l.vbi.name",
00190 "V4L vbi");
00191 else
00192 ds_property_set_string (d, "v4l.vbi.name",
00193 product_name);
00194
00195 ds_add_capability (d, "v4l.vbi");
00196 } else if (strcmp (v4l_class, "video") == 0) {
00197 ds_property_set_string (d, "v4l.video.linux.sysfs_path",
00198 path);
00199 ds_property_set_int (d, "v4l.video.adapter", adapter_num);
00200 ds_property_set_string (d, "v4l.video.device", dev_file);
00201
00202 if (product_name == NULL)
00203 ds_property_set_string (d, "v4l.video.name",
00204 "V4L video");
00205 else
00206 ds_property_set_string (d, "v4l.video.name",
00207 product_name);
00208
00209 ds_add_capability (d, "v4l.video");
00210 } else if (strcmp (v4l_class, "radio") == 0) {
00211 ds_property_set_string (d, "v4l.radio.linux.sysfs_path",
00212 path);
00213 ds_property_set_int (d, "v4l.radio.adapter", adapter_num);
00214 ds_property_set_string (d, "v4l.radio.device", dev_file);
00215
00216 if (product_name == NULL)
00217 ds_property_set_string (d, "v4l.radio.name",
00218 "V4L radio");
00219 else
00220 ds_property_set_string (d, "v4l.radio.name",
00221 product_name);
00222
00223 ds_add_capability (d, "v4l.radio");
00224 }
00225
00226 sysdevice_sysfs_path = class_device->sysdevice->path;
00227
00228
00229
00230
00231
00232 ds_device_async_find_by_key_value_string
00233 ("linux.sysfs_path_device", sysdevice_sysfs_path, TRUE,
00234 visit_class_device_v4l_got_sysdevice, (void *) d, NULL,
00235 is_probing ? 0 : HAL_LINUX_HOTPLUG_TIMEOUT);
00236 }
00237
00245 static void
00246 visit_class_device_v4l_got_sysdevice (HalDevice * sysdevice,
00247 void *data1, void *data2)
00248 {
00249 HalDevice *d = (HalDevice *) data1;
00250
00251
00252
00253 if (sysdevice == NULL) {
00254 HAL_ERROR (("No sysdevice for V4L device!"));
00255 ds_device_destroy (d);
00256 return;
00257 } else {
00258 ds_device_merge (sysdevice, d);
00259 }
00260
00261 ds_device_destroy (d);
00262 }
00263
00267 void
00268 linux_class_v4l_init ()
00269 {
00270 }
00271
00276 void
00277 linux_class_v4l_detection_done ()
00278 {
00279 }
00280
00284 void
00285 linux_class_v4l_shutdown ()
00286 {
00287 }
00288