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

linux_class_scsi.c

00001 /***************************************************************************
00002  * CVSID: $Id: linux_class_scsi.c,v 1.7 2004/01/07 23:25:53 david Exp $
00003  *
00004  * hal_scsi.c : SCSI 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 "../logger.h"
00040 #include "../device_store.h"
00041 #include "linux_class_scsi.h"
00042 
00059 static char* scsi_host_compute_udi(HalDevice* d, int append_num)
00060 {
00061     const char* format;
00062     static char buf[256];
00063 
00064     if( append_num==-1 )
00065         format = "/org/freedesktop/Hal/devices/scsi_host_%d";
00066     else
00067         format = "/org/freedesktop/Hal/devices/scsi_host_%d-%d";
00068 
00069     snprintf(buf, 256, format, 
00070              ds_property_get_int(d, "scsi_host.host"),
00071              append_num);
00072     
00073     return buf;
00074 }
00075 
00076 
00086 static char* scsi_device_compute_udi(HalDevice* d, int append_num)
00087 {
00088     const char* format;
00089     static char buf[256];
00090 
00091     if( append_num==-1 )
00092         format = "/org/freedesktop/Hal/devices/scsi_device_%d_%d_%d_%d";
00093     else
00094         format = "/org/freedesktop/Hal/devices/scsi_device_%d_%d_%d_%d-%d";
00095 
00096     snprintf(buf, 256, format, 
00097              ds_property_get_int(d, "scsi_device.host"),
00098              ds_property_get_int(d, "scsi_device.bus"),
00099              ds_property_get_int(d, "scsi_device.target"),
00100              ds_property_get_int(d, "scsi_device.lun"),
00101              append_num);
00102     
00103     return buf;
00104 }
00105 
00106 
00107 /* fwd decl */
00108 static void visit_class_device_scsi_host_got_parent(HalDevice* parent, 
00109                                                     void* data1, void* data2);
00110 
00119 void visit_class_device_scsi_host(const char* path, 
00120                                   struct sysfs_class_device* class_device)
00121 {
00122     HalDevice* d;
00123     char* parent_sysfs_path;
00124     const char* last_elem;
00125     int host_num;
00126 
00127     if( class_device->sysdevice==NULL )
00128     {
00129         HAL_INFO(("Skipping virtual class device at path %s\n", path));
00130         return;
00131     }
00132 
00133     HAL_INFO(("scsi_host: sysdevice_path=%s, path=%s\n", class_device->sysdevice->path, path));
00134 
00137     d = ds_device_new();
00138     ds_property_set_string(d, "info.bus", "scsi_host");
00139     ds_property_set_string(d, "linux.sysfs_path", path);
00140     ds_property_set_string(d, "linux.sysfs_path_device", 
00141                            class_device->sysdevice->path);
00142 
00143     /* Sets last_elem to host14 in path=/sys/class/scsi_host/host14 */
00144     last_elem = get_last_element(path);
00145     sscanf(last_elem, "host%d", &host_num);
00146     ds_property_set_int(d, "scsi_host.host", host_num);
00147 
00148 
00149     /* guestimate product name */
00150     ds_property_set_string(d, "info.product", "SCSI Host Interface");
00151 
00152     parent_sysfs_path = get_parent_sysfs_path(class_device->sysdevice->path);
00153 
00154     /* Find parent; this happens asynchronously as our parent might
00155      * be added later. If we are probing this can't happen so the
00156      * timeout is set to zero in that event..
00157      */
00158     ds_device_async_find_by_key_value_string(
00159         "linux.sysfs_path_device",
00160         parent_sysfs_path, 
00161         TRUE,
00162         visit_class_device_scsi_host_got_parent,
00163         (void*) d, NULL, 
00164         is_probing ? 0 :
00165         HAL_LINUX_HOTPLUG_TIMEOUT);
00166 
00167     free(parent_sysfs_path);
00168 }
00169 
00177 static void visit_class_device_scsi_host_got_parent(HalDevice* parent, 
00178                                                     void* data1, void* data2)
00179 {
00180     char* new_udi = NULL;
00181     HalDevice* new_d = NULL;
00182     HalDevice* d = (HalDevice*) data1;
00183 
00184     /*printf("parent=0x%08x\n", parent);*/
00185 
00186     if( parent!=NULL )
00187     {
00188         ds_property_set_string(d, "info.parent", parent->udi);
00189         find_and_set_physical_device(d);
00190         ds_property_set_bool(d, "info.virtual", TRUE);
00191     }
00192     else
00193     {
00194         HAL_ERROR(("No parent for SCSI device!"));
00195         ds_device_destroy(d);
00196         return;
00197     }
00198 
00199     /* Compute a proper UDI (unique device id) and try to locate a persistent
00200      * unplugged device or simple add this new device...
00201      */
00202     new_udi = rename_and_merge(d, scsi_host_compute_udi, "scsi_host");
00203     if( new_udi!=NULL )
00204     {
00205         new_d = ds_device_find(new_udi);
00206         if( new_d!=NULL )
00207         {
00208             ds_gdl_add(new_d);
00209         }
00210     }
00211 }
00212 
00213 
00214 /* fwd decl */
00215 static void visit_class_device_scsi_device_got_parent(HalDevice* parent, 
00216                                                      void* data1, void* data2);
00217 
00226 void visit_class_device_scsi_device(const char* path, 
00227                                     struct sysfs_class_device* class_device)
00228 {
00229     HalDevice* d;
00230     char* parent_sysfs_path;
00231     const char* last_elem;
00232     int host_num, bus_num, target_num, lun_num;
00233 
00234     if( class_device->sysdevice==NULL )
00235     {
00236         HAL_INFO(("Skipping virtual class device at path %s\n", path));
00237         return;
00238     }
00239 
00240     /*printf("scsi_device: sysdevice_path=%s, path=%s\n", class_device->sysdevice->path, path);*/
00241 
00244     d = ds_device_new();
00245     ds_property_set_string(d, "info.bus", "scsi_device");
00246     ds_property_set_string(d, "linux.sysfs_path", path);
00247     ds_property_set_string(d, "linux.sysfs_path_device", 
00248                            class_device->sysdevice->path);
00249 
00250     /* Sets last_elem to 1:2:3:4 in path=/sys/class/scsi_host/host23/1:2:3:4 */
00251     last_elem = get_last_element(path);
00252     sscanf(last_elem, "%d:%d:%d:%d", 
00253            &host_num, &bus_num, &target_num, &lun_num);
00254     ds_property_set_int(d, "scsi_device.host", host_num);
00255     ds_property_set_int(d, "scsi_device.bus", bus_num);
00256     ds_property_set_int(d, "scsi_device.target", target_num);
00257     ds_property_set_int(d, "scsi_device.lun", lun_num);
00258 
00259 
00260     /* guestimate product name */
00261     ds_property_set_string(d, "info.product", "SCSI Interface");
00262 
00263 
00264     parent_sysfs_path = get_parent_sysfs_path(class_device->sysdevice->path);
00265 
00266     /* Find parent; this happens asynchronously as our parent might
00267      * be added later. If we are probing this can't happen so the
00268      * timeout is set to zero in that event..
00269      */
00270     ds_device_async_find_by_key_value_string(
00271         "linux.sysfs_path_device",
00272         parent_sysfs_path,
00273         TRUE,
00274         visit_class_device_scsi_device_got_parent,
00275         (void*) d, NULL, 
00276         is_probing ? 0 :
00277         HAL_LINUX_HOTPLUG_TIMEOUT);
00278 
00279     free(parent_sysfs_path);
00280 }
00281 
00289 static void visit_class_device_scsi_device_got_parent(HalDevice* parent, 
00290                                                       void* data1, void* data2)
00291 {
00292     char* new_udi = NULL;
00293     HalDevice* new_d = NULL;
00294     HalDevice* d = (HalDevice*) data1;
00295 
00296     if( parent!=NULL )
00297     {
00298         ds_property_set_string(d, "info.parent", parent->udi);
00299         find_and_set_physical_device(d);
00300         ds_property_set_bool(d, "info.virtual", TRUE);
00301     }
00302     else
00303     {
00304         HAL_ERROR(("No parent for SCSI device!"));
00305         ds_device_destroy(d);
00306         return;
00307     }
00308 
00309     /* Compute a proper UDI (unique device id) and try to locate a persistent
00310      * unplugged device or simple add this new device...
00311      */
00312     new_udi = rename_and_merge(d, scsi_device_compute_udi, "scsi_device");
00313     if( new_udi!=NULL )
00314     {
00315         new_d = ds_device_find(new_udi);
00316         if( new_d!=NULL )
00317         {
00318             ds_gdl_add(new_d);
00319         }
00320     }
00321 }
00322 
00326 void linux_class_scsi_init()
00327 {
00328 }
00329 
00334 void linux_class_scsi_detection_done()
00335 {
00336 }
00337 
00341 void linux_class_scsi_shutdown()
00342 {
00343 }
00344 

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