def __init__(self, dm, config, name):
        Device.__init__(self, dm, config, name)
        self._DGLock = Mutex(Qt.QMutex.Recursive)  ## protects access to _DGHolding, _DGConfig
        ## Do some sanity checks here on the configuration

        # 'channels' key is expected; for backward compatibility we just use the top-level config.
        config = config.get('channels', config)
        self._DGConfig = config
        self._DGHolding = {}
        for ch in config:
            if config[ch]['type'][0] != 'a' and ('scale' in config[ch] or 'offset' in config[ch]):
                raise Exception("Scale/offset only allowed for analog channels. (%s.%s)" % (name, ch))

            if 'scale' not in config[ch]:
                config[ch]['scale'] = 1  ## must be int to prevent accidental type conversion on digital data
            if 'offset' not in config[ch]:
                config[ch]['offset'] = 0
            if config[ch].get('invert', False):
                if config[ch]['type'][0] != 'd':
                    raise Exception("Inversion only allowed for digital channels. (%s.%s)" % (name, ch))
                config[ch]['scale'] = -1
                config[ch]['offset'] = -1

            # print "chan %s scale %f" % (ch, config[ch]['scale'])
            if 'holding' not in config[ch]:
                config[ch]['holding'] = 0.0

            ## It is possible to create virtual channels with no real hardware connection
            if 'device' not in config[ch]:
                # print "Assuming channel %s is virtual:" % ch, config[ch]
                config[ch]['virtual'] = True

            ## set holding value for all output channels now
            if config[ch]['type'][1] == 'o':
                self.setChanHolding(ch, config[ch]['holding'])
            # self._DGHolding[ch] = config[ch]['holding']

        dm.declareInterface(name, ['daqChannelGroup'], self)
        for ch in config:
            dm.declareInterface(name + "." + ch, ['daqChannel'], ChannelHandle(self, ch))