Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

opcmciasystem.cpp

Go to the documentation of this file.
00001 /*
00002                              This file is part of the Opie Project
00003               =.             (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
00004             .=l.
00005            .>+-=
00006  _;:,     .>    :=|.         This program is free software; you can
00007 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00008 :`=1 )Y*s>-.--   :           the terms of the GNU Library General Public
00009 .="- .-=="i,     .._         License as published by the Free Software
00010  - .   .-<_>     .<>         Foundation; version 2 of the License.
00011      ._= =}       :
00012     .%`+i>       _;_.
00013     .i_,=:_.      -<s.       This program is distributed in the hope that
00014      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00015     : ..    .:,     . . .    without even the implied warranty of
00016     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00017   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00018 ..}^=.=       =       ;      Library General Public License for more
00019 ++=   -.     .`     .:       details.
00020  :     =  ...= . :.=-
00021  -.   .:....=;==+<;          You should have received a copy of the GNU
00022   -_. . .   )=.  =           Library General Public License along with
00023     --        :-=`           this library; see the file COPYING.LIB.
00024                              If not, write to the Free Software Foundation,
00025                              Inc., 59 Temple Place - Suite 330,
00026                              Boston, MA 02111-1307, USA.
00027 
00028 */
00029 
00030 #include "opcmciasystem.h"
00031 using namespace Opie::Core;
00032 
00033 /* OPIE */
00034 #include <opie2/odebug.h>
00035 
00036 /* QT */
00037 #include <qfile.h>
00038 #include <qtextstream.h>
00039 
00040 /* STD */
00041 #include <errno.h>
00042 #include <fcntl.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <sys/ioctl.h>
00046 #include <sys/types.h>
00047 #include <sys/stat.h>
00048 #include <unistd.h>
00049 
00050 #define PROC_DEVICES "/proc/devices"
00051 
00052 /*======================================================================================
00053  * OPcmciaSystem
00054  *======================================================================================*/
00055 
00056 OPcmciaSystem* OPcmciaSystem::_instance = 0;
00057 
00058 OPcmciaSystem::OPcmciaSystem()
00059               :_major( 0 )
00060 {
00061     qDebug( "OPcmciaSystem::OPcmciaSystem()" );
00062 
00063     // get major node number out of /proc/devices
00064     QFile procfile( PROC_DEVICES );
00065     if ( procfile.exists() && procfile.open( IO_ReadOnly ) )
00066     {
00067         QTextStream devstream( &procfile );
00068         devstream.readLine(); // skip header
00069         while ( !devstream.atEnd() && !_major )
00070         {
00071             int nodenumber;
00072             QString driver;
00073             devstream >> nodenumber >> driver;
00074             if ( driver == "pcmcia" )
00075             {
00076                 qDebug( "OPcmciaSystem::OPcmciaSystem(): gotcha! pcmcia node number = %d", nodenumber );
00077                 _major = nodenumber;
00078                 break;
00079             }
00080         }
00081     }
00082     else
00083     {
00084         qWarning( "OPcmciaSystem::OPcmciaSystem() - can't open /proc/devices - continuing with limited functionality." );
00085     }
00086 
00087     synchronize();
00088 }
00089 
00090 void OPcmciaSystem::synchronize()
00091 {
00092     qDebug( "OPcmciaSystem::synchronize()" );
00093     _interfaces.clear();
00094 
00095     //NOTE: We _could_ use ioctl's here as well, however we want to know if
00096     //      the card is recognized by the cardmgr (hence has a valid binding)
00097     //      If it is not recognized yet, userland may want to provide a configuration dialog
00098     //TODO: Revise for pcmciautils
00099 
00100     QString fileName;
00101     if ( QFile::exists( "/var/run/stab" ) ) { fileName = "/var/run/stab"; }
00102     else if ( QFile::exists( "/var/state/pcmcia/stab" ) ) { fileName = "/var/state/pcmcia/stab"; }
00103     else { fileName = "/var/lib/pcmcia/stab"; }
00104     QFile cardinfofile( fileName );
00105     if ( !cardinfofile.exists() || !cardinfofile.open( IO_ReadOnly ) )
00106     {
00107         qWarning( "pcmcia info file not found or unaccessible" );
00108         return;
00109     }
00110     QTextStream cardinfo( &cardinfofile );
00111     while ( !cardinfo.atEnd() )
00112     {
00113         QString strSocket;
00114         int numSocket;
00115         char colon;
00116         QString cardName;
00117         cardinfo >> strSocket >> numSocket >> colon;
00118         cardName = cardinfo.readLine().stripWhiteSpace();
00119         qDebug( "strSocket = '%s', numSocket = '%d', colon = '%c', cardName = '%s'", (const char*) strSocket, numSocket, colon, ( const char*) cardName );
00120         if ( strSocket == "Socket" && colon == ':' )
00121         {
00122             _interfaces.append( new OPcmciaSocket( _major, numSocket, this, (const char*) cardName ) );
00123         }
00124         else
00125         {
00126             continue;
00127         }
00128     }
00129 }
00130 
00131 
00132 int OPcmciaSystem::count() const
00133 {
00134     return _interfaces.count();
00135 }
00136 
00137 
00138 int OPcmciaSystem::cardCount() const
00139 {
00140     int nonEmpty = 0;
00141     OPcmciaSystem::CardIterator it = iterator();
00142     while ( it.current() )
00143     {
00144         if ( !it.current()->isEmpty() ) nonEmpty++;
00145         ++it;
00146     }
00147     return nonEmpty;
00148 }
00149 
00150 
00151 OPcmciaSocket* OPcmciaSystem::socket( unsigned int number )
00152 {
00153     return _interfaces.at( number );
00154 }
00155 
00156 
00157 void OPcmciaSystem::restart()
00158 {
00159     //FIXME Use OProcess or something that allows more control
00160     ::system( "/etc/init.d/pcmcia restart" );
00161 }
00162 
00163 
00164 OPcmciaSystem* OPcmciaSystem::instance()
00165 {
00166     if ( !_instance ) _instance = new OPcmciaSystem();
00167     return _instance;
00168 }
00169 
00170 
00171 OPcmciaSystem::CardIterator OPcmciaSystem::iterator() const
00172 {
00173     return OPcmciaSystem::CardIterator( _interfaces );
00174 }
00175 
00176 
00177 /*======================================================================================
00178  * OPcmciaSocket
00179  *======================================================================================*/
00180 
00181 OPcmciaSocket::OPcmciaSocket( int major, int socket, QObject* parent, const char* name )
00182                  :QObject( parent, name ), _major( major ), _socket( socket )
00183 {
00184     qDebug( "OPcmciaSocket::OPcmciaSocket()" );
00185     init();
00186 }
00187 
00188 
00189 OPcmciaSocket::~OPcmciaSocket()
00190 {
00191     qDebug( "OPcmciaSocket::~OPcmciaSocket()" );
00192     cleanup();
00193 }
00194 
00195 
00196 /* internal */ void OPcmciaSocket::init()
00197 {
00198     // open control socket and gather file descriptor
00199     if ( _major )
00200     {
00201         dev_t dev = makedev( _major, _socket );
00202 
00203 #ifdef OPCMCIA_DEBUG
00204         QString filename = "/tmp/opcmciasystem-debug";
00205         if ( QFile::exists( filename ) )
00206 #else
00207         QString filename = QString().sprintf( "/tmp/opcmciasystem-%d", ::getpid() );
00208         if ( ::mknod( (const char*) filename, ( S_IFCHR|S_IREAD|S_IWRITE ), dev ) == 0 )
00209 #endif
00210         {
00211             _fd = ::open( (const char*) filename, O_RDONLY);
00212             if ( !_fd )
00213             {
00214                 qWarning( "OPcmciaSocket::init() - can't open control socket (%s)", strerror( errno ) );
00215             }
00216 #ifndef OPCMCIA_DEBUG
00217             else
00218             {
00219                 ::unlink( (const char*) filename );
00220             }
00221 #endif
00222         }
00223         else
00224         {
00225             qWarning( "OPcmciaSocket::init() - can't create device node '%s' (%s)", (const char*) filename, strerror( errno ) );
00226         }
00227     }
00228 }
00229 
00230 /* internal */ void OPcmciaSocket::cleanup()
00231 {
00232     // close control socket
00233 }
00234 
00235 /* internal */ bool OPcmciaSocket::getTuple( cisdata_t tuple ) const
00236 {
00237     _ioctlarg.tuple.DesiredTuple = tuple;
00238     _ioctlarg.tuple.Attributes = TUPLE_RETURN_COMMON;
00239     _ioctlarg.tuple.TupleOffset = 0;
00240 
00241     int result;
00242     result = ::ioctl(_fd, DS_GET_FIRST_TUPLE, &_ioctlarg);
00243     if ( result != 0 )
00244     {
00245         qWarning( "OPcmciaSocket::getTuple() - DS_GET_FIRST_TUPLE failed (%s)", strerror( errno ) );
00246         return false;
00247     }
00248 
00249     result = ::ioctl(_fd, DS_GET_TUPLE_DATA, &_ioctlarg);
00250     if ( result != 0 )
00251     {
00252         qWarning( "OPcmciaSocket::getTuple() - DS_GET_TUPLE_DATA failed (%s)", strerror( errno ) );
00253         return false;
00254     }
00255 
00256     result = ::ioctl( _fd, DS_PARSE_TUPLE, &_ioctlarg );
00257     if ( result != 0 )
00258     {
00259         qWarning( "OPcmciaSocket::getTuple() - DS_PARSE_TUPLE failed (%s)", strerror( errno ) );
00260         return false;
00261     }
00262 
00263     return true;
00264 }
00265 
00266 
00267 int OPcmciaSocket::number() const
00268 {
00269     return _socket;
00270 }
00271 
00272 
00273 QString OPcmciaSocket::identity() const
00274 {
00275     return ( strcmp( name(), "empty" ) == 0 ) ? "<Empty Socket>" : name();
00276 }
00277 
00278 
00279 const OPcmciaSocket::OPcmciaSocketCardStatus OPcmciaSocket::status() const
00280 {
00281     cs_status_t cs_status;
00282     cs_status.Function = 0;
00283     int result = ::ioctl( _fd, DS_GET_STATUS, &cs_status );
00284     if ( result != 0 )
00285     {
00286         qWarning( "OPcmciaSocket::status() - DS_GET_STATUS failed (%s)", strerror( errno ) );
00287         // return ( errno == -ENODEV ) ? Empty : Unknown;
00288         return Unknown;
00289     }
00290     else
00291     {
00292         qDebug( " card   status = 0x%08x", cs_status.CardState );
00293         qDebug( " socket status = 0x%08x", cs_status.SocketState );
00294         return (OPcmciaSocket::OPcmciaSocketCardStatus) (cs_status.CardState + cs_status.SocketState);
00295     }
00296 }
00297 
00298 
00299 bool OPcmciaSocket::isUnsupported() const
00300 {
00301     return ( strcmp( name(), "unsupported card" ) == 0 );
00302 }
00303 
00304 
00305 bool OPcmciaSocket::isEmpty() const
00306 {
00307     return !(status() & ( Occupied | OccupiedCardBus ));
00308 }
00309 
00310 
00311 bool OPcmciaSocket::isSuspended() const
00312 {
00313     return status() & Suspended;
00314 }
00315 
00316 
00317 bool OPcmciaSocket::eject()
00318 {
00319     return ::ioctl( _fd, DS_EJECT_CARD ) != -1;
00320 }
00321 
00322 
00323 bool OPcmciaSocket::insert()
00324 {
00325     return ::ioctl( _fd, DS_INSERT_CARD ) != -1;
00326 }
00327 
00328 
00329 bool OPcmciaSocket::suspend()
00330 {
00331     return ::ioctl( _fd, DS_SUSPEND_CARD ) != -1;
00332 }
00333 
00334 
00335 bool OPcmciaSocket::resume()
00336 {
00337     return ::ioctl( _fd, DS_RESUME_CARD ) != -1;
00338 }
00339 
00340 
00341 bool OPcmciaSocket::reset()
00342 {
00343     return ::ioctl( _fd, DS_RESET_CARD ) != -1;
00344 }
00345 
00346 
00347 QStringList OPcmciaSocket::productIdentityVector() const
00348 {
00349     QStringList list;
00350     cistpl_vers_1_t *vers = &_ioctlarg.tuple_parse.parse.version_1;
00351     vers->ns = 0; // number of strings
00352     if ( getTuple( CISTPL_VERS_1 ) )
00353     {
00354         qDebug( " NUMBER_OF_PRODIDs = %d", vers->ns );
00355         for ( int i = 0; i < QMIN( CISTPL_VERS_1_MAX_PROD_STRINGS, vers->ns ); ++i )
00356         {
00357             qDebug( " PRODID = '%s'", vers->str+vers->ofs[i] );
00358             list += vers->str+vers->ofs[i];
00359         }
00360     }
00361     else
00362     {
00363         list += "<unknown>";
00364     }
00365     return list;
00366 }
00367 
00368 
00369 QString OPcmciaSocket::productIdentity() const
00370 {
00371     return productIdentityVector().join( " " ).stripWhiteSpace();
00372 }
00373 
00374 
00375 QString OPcmciaSocket::manufacturerIdentity() const
00376 {
00377     cistpl_manfid_t *manfid = &_ioctlarg.tuple_parse.parse.manfid;
00378     if ( getTuple( CISTPL_MANFID ) )
00379     {
00380         return QString().sprintf( "0x%04x, 0x%04x", manfid->manf, manfid->card );
00381     }
00382     else
00383         return "<unknown>";
00384 }
00385 
00386 
00387 QString OPcmciaSocket::function() const
00388 {
00389     cistpl_funcid_t *funcid = &_ioctlarg.tuple_parse.parse.funcid;
00390     if ( getTuple( CISTPL_FUNCID ) )
00391     {
00392         switch ( funcid->func )
00393         {
00394             case 0: return "Multifunction"; break;
00395             case 1: return "Memory"; break;
00396             case 2: return "Serial"; break;
00397             case 3: return "Parallel"; break;
00398             case 4: return "Fixed Disk"; break;
00399             case 5: return "Video"; break;
00400             case 6: return "Network"; break;
00401             case 7: return "AIMS"; break;
00402             case 8: return "SCSI"; break;
00403             default: return "<unknown>"; break;
00404         }
00405     }
00406     else
00407     {
00408         return "<unknown>";
00409     }
00410 }

Generated on Sat Nov 5 16:16:07 2005 for OPIE by  doxygen 1.4.2