[pkg-fso-commits] [SCM] FSO frameworkd Debian packaging branch, debian, updated. upstream/0.9.5.5-717-g0f98819

Michael 'Mickey' Lauer mickey at vanille-media.de
Sat Aug 6 08:17:26 UTC 2011


The following commit has been merged in the debian branch:
commit b3f5e4b380c934f7246ef93799919afc6e90c0cb
Merge: 3fd21e9b756c0a820bd8b17632bb0c3a35f1360e a9f4779e0749ec89f9a0d502ae0fe5845bf5024d
Author: Michael 'Mickey' Lauer <mickey at vanille-media.de>
Date:   Wed Jul 15 19:24:55 2009 +0200

    Merge commit 'origin/mickey/full-csd-handling'

diff --combined framework/subsystems/ogsmd/gsm/channel.py
index 69da2ad,7f47b20..d7f305d
--- a/framework/subsystems/ogsmd/gsm/channel.py
+++ b/framework/subsystems/ogsmd/gsm/channel.py
@@@ -14,9 -14,10 +14,9 @@@ This module provides communication chan
  transport their data over a (virtual) serial line.
  """
  
 -__version__ = "0.9.18"
 +__version__ = "0.9.18.2"
  MODULE_NAME = "ogsmd.channel"
  
 -from ogsmd.gsm.decor import logged
  import parser
  
  import gobject # pygobject
@@@ -61,6 -62,7 +61,6 @@@ class VirtualChannel( object )
      #
      # public API
      #
 -    @logged
      def __init__( self, pathfactory, name=None, **kwargs ):
          """Construct"""
          self.pathfactory = pathfactory
@@@ -73,13 -75,13 +73,13 @@@
      def __repr__( self ):
          return "<%s via %s>" % ( self.__class__.__name__, self.serial.port if self.serial is not None else "unknown" )
  
 -    @logged
      def open( self, path=None ):
          """
          Allocate a channel and opens a serial port.
          Returns True, if successful. False, otherwise.
          """
 -        assert not self.connected, "already connected"
 +        if self.connected:
 +            raise ValueError( "already connected" )
  
          # gather path
          path = self.pathfactory( self.name )
@@@ -137,6 -139,7 +137,6 @@@
          """
          pass
  
 -    @logged
      def suspend( self, ok_callback, error_callback ):
          """
          Called when the channel needs to be prepared for a suspend.
@@@ -145,6 -148,7 +145,6 @@@
          """
          ok_callback( self )
  
 -    @logged
      def resume( self, ok_callback, error_callback ):
          """
          Called when the channel needs to reinit after resume.
@@@ -153,10 -157,12 +153,10 @@@
          """
          ok_callback( self )
  
 -    @logged
      def write( self, data ):
          """Write data to the transport."""
          self._write( data )
  
 -    @logged
      def freeze( self ):
          """Pause reading from the transport."""
          if not self.watchReadyToRead:
@@@ -164,13 -170,15 +164,13 @@@
          else:
              gobject.source_remove( self.watchReadyToRead )
  
      def thaw( self ):
          """Resume reading from the transport."""
          if not self.watchReadyToRead:
 -            logger.warning( "%s: thaw() called with watch being already setup!", self )
 +            logger.warning( "%s: thaw() called with watch being already setup", self )
          else:
              self.watchReadyToRead = gobject.io_add_watch( self.serial.fd, gobject.IO_IN, self._readyToRead, priority=PRIORITY_RTR )
  
 -    @logged
      def close( self ):
          """
          Close the serial port and free the virtual channel.
@@@ -189,6 -197,12 +189,12 @@@
          self.connected = self.serial.isOpen()
          return not self.connected
  
+     def port( self ):
+         """
+         Return name of transport.
+         """
+         return self.serial.port
+ 
      #
      # hooks
      #
@@@ -219,11 -233,11 +225,11 @@@
      #
      # private API
      #
 -    @logged
      def _hup( self, source, condition ):
          """Called, if there is a HUP condition on the source."""
 -        assert source == self.serial.fd, "HUP on bogus source"
 -        assert condition == gobject.IO_HUP, "HUP on bogus condition"
 +        if ( source != self.serial.fd or condition != gobject.IO_HUP ):
 +            logger.warning( "ready to read, but bogus condition %d or source %d. Ignoring", condition, source )
 +            return False
          logger.info( "%s: HUP on socket" % self )
  
          self._hookHandleHupCondition()
@@@ -232,10 -246,9 +238,10 @@@
  
      def _readyToRead( self, source, condition ):
          """Called, if data is available on the source."""
 -        assert source == self.serial.fd, "ready to read on bogus source"
 -        assert condition == gobject.IO_IN, "ready to read on bogus condition"
 -        logger.debug( "%s: _readyToRead: watch timeout = %s", self, repr( self.watchTimeout ) )
 +        if ( source != self.serial.fd or condition != gobject.IO_IN ):
 +            logger.warning( "ready to read, but bogus condition %d or source %d. Ignoring", condition, source )
 +            return False
 +        #logger.debug( "%s: _readyToRead: watch timeout = %s", self, repr( self.watchTimeout ) )
  
          self._hookPreReading()
          data = self._lowlevelRead()
@@@ -260,10 -273,9 +266,10 @@@
  
      def _readyToSend( self, source, condition ):
          """Called, if source is ready to receive data."""
 -        assert source == self.serial.fd, "ready to write on bogus source"
 -        assert condition == gobject.IO_OUT, "ready to write on bogus condition"
 -        logger.debug( "%s: _readyToSend: watch timeout = %s", self, repr( self.watchTimeout ) )
 +        if ( source != self.serial.fd or condition != gobject.IO_OUT ):
 +            logger.warning( "ready to send, but bogus condition %d or source %d. Ignoring", condition, source )
 +            return False
 +        #logger.debug( "%s: _readyToSend: watch timeout = %s", self, repr( self.watchTimeout ) )
  
          if False:
              # make sure nothing has been queued up in the buffer in the meantime
@@@ -278,6 -290,7 +284,6 @@@
  
          return False # gobject, don't call me again
  
 -    @logged
      def __del__( self ):
          """Destruct"""
          self.close()
@@@ -368,6 -381,7 +374,6 @@@ class QueuedVirtualChannel( VirtualChan
              return
          self._handleCommandCancellation()
  
 -    #@logged
      def readyToSend( self ):
          """
          Reimplemented for internal purposes.
@@@ -386,7 -400,7 +392,7 @@@
          Reimplemented for internal purposes.
          """
  
 -        # restart timeout //FIXME: only if we were  waiting for a response?
 +        # restart timeout //FIXME: only if we were waiting for a response?
          if self.watchTimeout is not None:
              gobject.source_remove( self.watchTimeout )
              self.watchTimeout = gobject.timeout_add_seconds( self.timeout, self._handleCommandTimeout )
@@@ -439,6 -453,8 +445,6 @@@
      #
      # private API
      #
 -
 -    #@logged
      def _handleCommandCancellation( self ):
          """
          Called, when the current command should be cancelled.
@@@ -446,9 -462,7 +452,9 @@@
          According to v25ter, this can be done by sending _any_
          character to the serial line.
          """
 -        assert self.watchTimeout is not None, "no command to cancel"
 +        if self.watchTimeout is None:
 +            logger.warning( "no command to cancel" )
 +            return
          # we have a timer, so lets stop it
          gobject.source_remove( self.watchTimeout )
          self.watchTimeout = None
@@@ -464,6 -478,7 +470,6 @@@
          #   reqstring, ok_cb, error_cb, timeout = request
          #   error_cb( reqstring.strip(), ( "cancel", timeout ) )
  
 -    #@logged
      def _handleUnsolicitedResponse( self, response ):
          """
          Called from parser, when an unsolicited response has been parsed.
@@@ -471,6 -486,7 +477,6 @@@
          self.handleUnsolicitedResponse( response )
          return self.isWaitingForResponse() # parser needs to know the current status
  
 -    #@logged
      def _handleResponseToRequest( self, response ):
          """
          Called from parser, when a response to a request has been parsed.
@@@ -487,6 -503,7 +493,6 @@@
              self.watchReadyToSend = gobject.io_add_watch( self.serial.fd, gobject.IO_OUT, self._readyToSend, priority=PRIORITY_RTS )
          return self.isWaitingForResponse() # parser needs to know the current status
  
 -    #@logged
      def _handleCommandTimeout( self ):
          """
          Called from mainloop, when a command does not get a response within a certain timeout.
@@@ -498,9 -515,6 +504,9 @@@
          self.watchTimeout = None
          self.serial.write( "\x1A" )
          self.handleCommandTimeout( self.q.get() )
 +        # relaunch
 +        if not self.watchReadyToSend:
 +            self.watchReadyToSend = gobject.io_add_watch( self.serial.fd, gobject.IO_OUT, self._readyToSend, priority=PRIORITY_RTS )
          return False
  
  #=========================================================================#
@@@ -532,11 -546,10 +538,11 @@@ class DelegateChannel( QueuedVirtualCha
          """
          Set a delegate object to which all unsolicited responses are delegated first.
          """
 -        assert self.delegate is None, "delegate already set"
 +        if self.delegate is not None:
 +            logger.warning( "delegate already set. Ignoring" )
 +            return
          self.delegate = object
  
 -    #@logged
      def _handleUnsolicitedResponse( self, response ):
          """
          Reimplemented for internal purposes.
@@@ -548,7 -561,7 +554,7 @@@
  
          data = response[0]
  
 -        if not self.delegate:
 +        if self.delegate is None:
              # no delegate installed, hand over to generic handler
              return self.handleUnsolicitedResponse( data )
  
@@@ -559,6 -572,8 +565,6 @@@
          command, values = data.split( ':', 1 )
  
          # convert unsolicited command to a method name
 -        # FIXME this actually quite assumes certain structure for unsolicited responses,
 -        # might think about making this more generic and/or override in AtCommandChannel
          command = command.replace( ' ', '_' ) # no spaces in Python identifiers
          methodname = "%s%s" % ( self.prefixmap[command[0]], command[1:] ) # no special characters
  
@@@ -588,7 -603,6 +594,7 @@@ class AtCommandChannel( DelegateChanne
  
      Commands are prefixed according to v25ter. Multiline commands are handled.
      """
 +
      def enqueue( self, command, response_cb=None, error_cb=None, prefixes=None ):
          """
          Enqueue a single line or multiline command. Multiline commands have
@@@ -600,17 -614,13 +606,17 @@@
              QueuedVirtualChannel.enqueue( self, "AT%s\r\n" % command, response_cb, error_cb, prefixes )
  
          elif len( commands ) == 2:
 -            def enqueueSecondOne( request, response, self=self, command = "%s\x1A" % commands[1], response_cb = response_cb, error_cb = error_cb, prefixes = prefixes ):
 -                if response == []:
 -                    QueuedVirtualChannel.enqueue( self, command, response_cb, error_cb, prefixes )
 -                else:
 -                    logger.error( "multiline command got '%s' response instead of '""'. What now?", response )
 +            QueuedVirtualChannel.enqueue( self, "AT%s\r" % commands[0], self.onMultilineCommandResponse, self.onMultilineCommandError, prefixes )
 +            QueuedVirtualChannel.enqueue( self, "%s\x1A" % commands[1], response_cb, error_cb, prefixes )
 +
 +    def onMultilineCommandResponse( self, request, response ):
 +        if response != []:
 +            logger.warning( "multiline command got bogus response '%s' after first line. pushing ERROR to upper layer" )
 +            self._handleResponseToRequest( "+EXT I: INTERNAL" )
  
 -            QueuedVirtualChannel.enqueue( self, "AT%s\r" % commands[0], enqueueSecondOne, error_cb, prefixes )
 +    def onMultilineCommandError( self, request, error ):
 +        logger.error( "multiline command got error after first line. pushing ERROR to upper layer" )
 +        self._handleResponseToRequest( "+EXT I: INTERNAL" )
  
      # you should not need to call this anymore
      enqueueRaw = QueuedVirtualChannel.enqueue
diff --combined framework/subsystems/ogsmd/modems/abstract/calling.py
index 0fd1504,0653114..7652b8c
--- a/framework/subsystems/ogsmd/modems/abstract/calling.py
+++ b/framework/subsystems/ogsmd/modems/abstract/calling.py
@@@ -12,12 -12,14 +12,14 @@@ Module: callin
  New style abstract call handling
  """
  
- __version__ = "0.9.1.2"
+ __version__ = "0.9.1.4"
  MODULE_NAME = "ogsmd.callhandler"
  
  from ogsmd import error
  from ogsmd.gsm import const
  
+ from framework.patterns.processguard import ProcessGuard
+ 
  import logging
  logger = logging.getLogger( MODULE_NAME )
  
@@@ -54,6 -56,54 +56,54 @@@ class CallHandler( object )
          return self._calls[1]["status"], self._calls[2]["status"]
  
      #
+     # additional support for data call handling with a customizable data call handler
+     #
+     def onActivateResult( self, request, response ):
+         """
+         Called after ATA
+         """
+         if response[0].startswith( "CONNECT" ): # data call succeeded
+             self._onDataCallEstablished()
+ 
+     def onInitiateResult( self, request, response ):
+         """
+         Called after ATDxyz
+         """
+         if response[0].startswith( "CONNECT" ): # data call succeeded
+             self._onDataCallEstablished()
+ 
+     def _onDataCallEstablished( self ):
+         logger.debug( "data call established" )
+         # if this is a data call, add the port where communication happens
+         self.csdid = callId = 1 if self._calls[1]["status"] == "active" else 2
+         self.csdchan = channel = self._object.modem.channel( "CallMediator" )
+         self.statusChangeFromNetwork( callId, { "status": "connect", "port": channel.port() } )
+ 
+         # check whether we have a data call handler registered
+         dataCallHandler = self._object.modem.data( "data-call-handler" )
+         if dataCallHandler is not None:
+             self.csdchan.freeze()
+             csd_commandline = dataCallHandler.split()
+             if not dataCallHandler.startswith( "/bin/sleep" ): # for debugging
+                 csd_commandline += [ channel.port(), self._calls[callId]["direction"] ]
+             self.csdproc = ProcessGuard( csd_commandline )
+             logger.info( "launching csd handler as commandline %s" % csd_commandline )
+             self.csdproc.execute( onExit=self._spawnedProcessDone )
+         else:
+             logger.info( "no csd handler registered" )
+ 
+     def _spawnedProcessDone( self, pid, exitcode, exitsignal ):
+         """
+         Called after CSD Handler exit.
+         """
+         logger.info( "csd handler exited with code %d, signal %d" % ( exitcode, exitsignal ) )
+         # unfreeze
+         self.csdchan.thaw()
+         # release call and resume normal operation
+         # self.release( self.csdid, self._object.modem.channel( "MiscMediator" ) )
+         self.releaseAll( self._object.modem.channel( "MiscMediator" ) )
+ 
+     #
      # called from mediators
      #
  
@@@ -141,10 -191,10 +191,10 @@@
      # deal with responses from call control commands
      #
      def responseFromChannel( self, request, response ):
 -        print "AT RESPONSE FROM CHANNEL=", response
 +        logger.debug( "response from channel to %s = %s", request, response )
  
      def errorFromChannel( self, request, response ):
 -        print "AT ERROR FROM CHANNEL=", response
 +        logger.error( "error from channel to %s = %s", request, response )
  
      #
      # synchronize status
@@@ -161,7 -211,7 +211,7 @@@
          self.statusChangeFromNetwork( callid, {"status": status} )
  
      def syncStatus_err( self, request, error ):
 -        print "AT ERROR FROM CHANNEL=", error
 +        logger.error( "error from channel to %s = %s", request, error )
  
      #
      # state machine actions following. micro states:
@@@ -189,7 -239,7 +239,7 @@@
      def state_release_release( self, action, *args, **kwargs ):
          if action == "initiate":
              dialstring, commchannel = args
-             commchannel.enqueue( "D%s" % dialstring, self.responseFromChannel, self.errorFromChannel )
+             commchannel.enqueue( "D%s" % dialstring, self.onInitiateResult, self.errorFromChannel )
              return 1
  
      def state_incoming_release( self, action, *args, **kwargs ):
@@@ -198,7 -248,7 +248,7 @@@
              return True
          elif action == "activate" and kwargs["index"] == 1:
              # FIXME handle data calls here
-             kwargs["channel"].enqueue( 'A' )
+             kwargs["channel"].enqueue( 'A', self.onActivateResult )
              return True
  
      def state_outgoing_release( self, action, *args, **kwargs ):

-- 
FSO frameworkd Debian packaging



More information about the pkg-fso-commits mailing list