# osmo_gsm_tester: class defining a Power Supply object
#
# Copyright (C) 2018 by sysmocom - s.f.m.c. GmbH
#
# Author: Pau Espin Pedrol <pespin@sysmocom.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import sispm
from usb.core import USBError

from ..core import log
from ..core.event_loop import MainLoop
from .powersupply import PowerSupply

class PowerSupplySispm(PowerSupply):
    """PowerSupply implementation using pysispm.

    The device object from sismpm is not cached into an attribute of the class
    instance because it is actually a libusb object keeping the device assigned
    to it until it destroyed, meaning it will block other users to use the whole
    device until the object is released. Instead, we pick the object in the
    smallest scope possible, and we re-try if we receive a "Resource Busy" error
    because we know it will be available in short time.
    """

    def _retry_usberr(self, func, *args):
        """Run function until it runs successfully, retry on spurious errors.

        Sometimes when operating the usb device, libusb reports the following spurious exception:
        [Errno 16] Resource busy -> This can appear if another instance is using the device.
        [Errno 110] Operation timed out

        Retrying after that it's usually enough.
        """
        while True:
            try:
                ret = func(*args)
                return ret
            except USBError as e:
                    if e.errno == 16 or e.errno==110:
                        self.log('skip usb error, retry', repr(e))
                        MainLoop.sleep(self, 0.1)
                        continue
                    raise e

    def _get_device(self):
        """Get the sispm device object.

        It should be kept alive as short as possible as it blocks other users
        from using the device until the object is released.
        """
        mydevid = self.conf.get('device')
        devices = self._retry_usberr(sispm.connect)
        for d in devices:
            did = self._retry_usberr(sispm.getid, d)
            self.dbg('detected device:', did)
            if did == mydevid:
                self.dbg('found matching device: %s' % did)
                return d
        return None


########################
# PUBLIC - INTERNAL API
########################
    def __init__(self, conf):
        super().__init__(conf, 'sispm')
        mydevid = conf.get('device')
        if mydevid is None:
            raise log.Error('No "device" attribute provided in supply conf!')
        self.set_name('sispm-'+mydevid)
        myport = conf.get('port')
        if myport is None:
            raise log.Error('No "port" attribute provided in power_supply conf!')
        if not int(myport):
            raise log.Error('Wrong non numeric "port" attribute provided in power_supply conf!')
        self.set_name('sispm-'+mydevid+'-'+myport)
        self.port = int(myport)
        device = self._get_device()
        if device is None:
            raise log.Error('device with with id %s not found!' % mydevid)
        dmin = self._retry_usberr(sispm.getminport, device)
        dmax = self._retry_usberr(sispm.getmaxport, device)
        if dmin > self.port or dmax < self.port:
            raise log.Error('Out of range "port" attribute provided in power_supply conf!')

    def is_powered(self):
        """Get whether the device is powered on or off."""
        return self._retry_usberr(sispm.getstatus, self._get_device(), self.port)

    def power_set(self, onoff):
        """Turn on (onoff=True) or off (onoff=False) the device."""
        if onoff:
            self.dbg('switchon')
            self._retry_usberr(sispm.switchon, self._get_device(), self.port)
        else:
            self.dbg('switchoff')
            self._retry_usberr(sispm.switchoff, self._get_device(), self.port)


# vim: expandtab tabstop=4 shiftwidth=4
