[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