Main Page | Modules | Data Structures | File List | Data Fields | Related Pages

linux_class_v4l.c

00001 /***************************************************************************
00002  * CVSID: $Id: linux_class_v4l.c,v 1.3 2004/01/19 21:03:40 david Exp $
00003  *
00004  * linux_class_v4l.c : V4L functions for sysfs-agent on Linux 2.6
00005  *
00006  * Copyright (C) 2003 David Zeuthen, <david@fubar.dk>
00007  *
00008  * Licensed under the Academic Free License version 2.0
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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 /* fwd decl */
00053 static void visit_class_device_v4l_got_sysdevice(HalDevice* parent, 
00054                                                  void* data1, void* data2);
00055 
00064 void visit_class_device_v4l(const char* path, 
00065                             struct sysfs_class_device* class_device)
00066 {
00067     HalDevice* d;
00068     struct sysfs_attribute* cur;
00069     char* sysdevice_sysfs_path;
00070     char* product_name = NULL;
00071     char attr_name[SYSFS_NAME_LEN];
00072     char v4l_class[32];
00073     const char* last_elem;
00074     int adapter_num;
00075     int len;
00076     int i;
00077     char buf[256];
00078     char dev_file[256];
00079 
00080     if( class_device->sysdevice==NULL )
00081     {
00082         HAL_INFO(("Skipping virtual class device at path %s\n", path));
00083         return;
00084     }
00085 
00086     HAL_INFO(("v4l: sysdevice_path=%s, path=%s\n", class_device->sysdevice->path, path));
00087 
00090     /* Sets last_elem to radio0 in path=/sys/class/video4linux/radio0 */
00091     last_elem = get_last_element(path);
00092     sscanf(last_elem, "%32[a-z]%d", v4l_class, &adapter_num);
00093 
00094     /* guestimate product name */
00095     dlist_for_each_data(sysfs_get_classdev_attributes(class_device), cur,
00096                         struct sysfs_attribute)
00097     {       
00098         if( sysfs_get_name_from_path(cur->path, 
00099                                      attr_name, SYSFS_NAME_LEN) != 0 )
00100             continue;
00101         
00102         /* strip whitespace */
00103         len = strlen(cur->value);
00104         for(i=len-1; isspace(cur->value[i]); --i)
00105             cur->value[i] = '\0';
00106         
00107         /*printf("attr_name=%s -> '%s'\n", attr_name, cur->value);*/
00108         
00109         if( strcmp(attr_name, "name")==0 )
00110            product_name = cur->value;
00111     }
00112 
00113     /* Ask udev about the device file if we are probing.. otherwise we'll just
00114      * receive a dbus message from udev later */
00115     dev_file[0] = '\0';
00116     if( is_probing )
00117     {
00118         int i;
00119         int sysfs_mount_path_len;
00120         char sysfs_path_trunc[SYSFS_NAME_LEN];
00121         char* udev_argv[7] = {"/sbin/udev", "-r", "-q", "name", "-p",
00122                               sysfs_path_trunc, NULL};
00123         char* udev_stdout;
00124         char* udev_stderr;
00125         int udev_exitcode;
00126 
00127         /* compute truncated sysfs path */
00128         sysfs_mount_path_len = strlen(sysfs_mount_path);
00129         if( strlen(path)>sysfs_mount_path_len )
00130         {
00131             strncpy(sysfs_path_trunc, path + sysfs_mount_path_len, 
00132                     SYSFS_NAME_LEN);
00133         }
00134         HAL_INFO(("*** sysfs_path_trunc = '%s'", sysfs_path_trunc));
00135         
00136         /* Now invoke udev */
00137         if( g_spawn_sync("/",
00138                          udev_argv,
00139                          NULL,
00140                          0,
00141                          NULL,
00142                          NULL,
00143                          &udev_stdout,
00144                          &udev_stderr,
00145                          &udev_exitcode,
00146              NULL)!=TRUE )
00147         {
00148             HAL_ERROR(("Couldn't invoke /sbin/udev"));
00149             goto error;
00150         }
00151         
00152         if( udev_exitcode!=0 )
00153         {
00154             HAL_ERROR(("/sbin/udev returned %d", udev_exitcode));
00155             goto error;
00156         }
00157         
00158         /* sanitize string returned by udev */
00159         for(i=0; udev_stdout[i]!=0; i++)
00160         {
00161             if( udev_stdout[i]=='\r' || udev_stdout[i]=='\n' )
00162             {
00163                 udev_stdout[i]=0;
00164                 break;
00165             }
00166         }
00167 
00168         strncat(dev_file, udev_stdout, 256);
00169                 
00171     }
00172     else
00173     {
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     {
00184         ds_property_set_string(d, "v4l.vbi.linux.sysfs_path", 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", "V4L vbi");
00190         else
00191             ds_property_set_string(d, "v4l.vbi.name", product_name);
00192 
00193         ds_add_capability(d, "v4l.vbi");
00194     }
00195     else if( strcmp(v4l_class, "video")==0 )
00196     {
00197         ds_property_set_string(d, "v4l.video.linux.sysfs_path", path);
00198         ds_property_set_int(d, "v4l.video.adapter", adapter_num);
00199         ds_property_set_string(d, "v4l.video.device", dev_file);
00200 
00201         if ( product_name==NULL )
00202             ds_property_set_string(d, "v4l.video.name", "V4L video");
00203         else
00204             ds_property_set_string(d, "v4l.video.name", product_name);
00205 
00206         ds_add_capability(d, "v4l.video");
00207     }
00208     else if( strcmp(v4l_class, "radio")==0 )
00209     {
00210         ds_property_set_string(d, "v4l.radio.linux.sysfs_path", path);
00211         ds_property_set_int(d, "v4l.radio.adapter", adapter_num);
00212         ds_property_set_string(d, "v4l.radio.device", dev_file);
00213 
00214         if ( product_name==NULL )
00215             ds_property_set_string(d, "v4l.radio.name", "V4L radio");
00216         else
00217             ds_property_set_string(d, "v4l.radio.name", product_name);
00218 
00219         ds_add_capability(d, "v4l.radio");
00220     }
00221  
00222     sysdevice_sysfs_path = class_device->sysdevice->path;
00223 
00224     /* Find sysdevice; this happens asynchronously as our sysdevice might
00225      * be added later. If we are probing this can't happen so the
00226      * timeout is set to zero in that event..
00227      */
00228     ds_device_async_find_by_key_value_string(
00229         "linux.sysfs_path_device",
00230         sysdevice_sysfs_path, 
00231         TRUE,
00232         visit_class_device_v4l_got_sysdevice,
00233         (void*) d, NULL, 
00234         is_probing ? 0 :
00235         HAL_LINUX_HOTPLUG_TIMEOUT);
00236 
00237     free(sysdevice_sysfs_path);
00238 }
00239 
00247 static void visit_class_device_v4l_got_sysdevice(HalDevice* sysdevice, 
00248                                                  void* data1, void* data2)
00249 {
00250     HalDevice* d = (HalDevice*) data1;
00251 
00252     /*printf("sysdevice=0x%08x\n", sysdevice);*/
00253 
00254     if( sysdevice==NULL )
00255     {
00256         HAL_ERROR(("No sysdevice for V4L device!"));
00257         ds_device_destroy(d);
00258         return;
00259     }
00260     else
00261     {
00262         ds_device_merge(sysdevice, d);
00263     }
00264 
00265     ds_device_destroy(d);
00266 }
00267 
00271 void linux_class_v4l_init()
00272 {
00273 }
00274 
00279 void linux_class_v4l_detection_done()
00280 {
00281 }
00282 
00286 void linux_class_v4l_shutdown()
00287 {
00288 }
00289 

Generated on Sat Feb 7 22:11:47 2004 for HAL by doxygen 1.3.5