def setup_swapchain_depth_stencil(recreate=False):
    global depth_format, depth_stencil, depth_alloc, depth_view

    if recreate:
        hvk.destroy_image_view(api, device, depth_view)
        hvk.destroy_image(api, device, depth_stencil)
        hvk.free_memory(api, device, depth_alloc)

    width, height = window.dimensions()

    # Depth stencil attachment setup
    depth_format = None
    depth_formats = (vk.FORMAT_D32_SFLOAT_S8_UINT, vk.FORMAT_D24_UNORM_S8_UINT,
                     vk.FORMAT_D16_UNORM_S8_UINT)
    for fmt in depth_formats:
        prop = hvk.physical_device_format_properties(api, physical_device, fmt)
        if IntFlag(vk.FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) in IntFlag(
                prop.optimal_tiling_features):
            depth_format = fmt
            break

    if depth_format is None:
        raise RuntimeError("Failed to find a suitable depth stencil format.")

    # Depth stencil image creation
    depth_stencil = hvk.create_image(
        api, device,
        hvk.image_create_info(format=depth_format,
                              extent=vk.Extent3D(width=width,
                                                 height=height,
                                                 depth=1),
                              usage=vk.IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT
                              | vk.IMAGE_USAGE_TRANSFER_SRC_BIT))

    # Depth stencil image memory
    image_memreq = hvk.image_memory_requirements(api, device, depth_stencil)
    mt_index = find_memory_type(vk.MEMORY_HEAP_DEVICE_LOCAL_BIT,
                                vk.MEMORY_PROPERTY_DEVICE_LOCAL_BIT)

    depth_stencil_size = image_memreq.size * 2
    depth_alloc = hvk.allocate_memory(
        api, device,
        hvk.memory_allocate_info(allocation_size=depth_stencil_size,
                                 memory_type_index=mt_index))

    hvk.bind_image_memory(api, device, depth_stencil, depth_alloc)

    # Depth stencil image view
    depth_view = hvk.create_image_view(
        api, device,
        hvk.image_view_create_info(
            image=depth_stencil,
            format=depth_format,
            subresource_range=hvk.image_subresource_range(
                aspect_mask=vk.IMAGE_ASPECT_DEPTH_BIT
                | vk.IMAGE_ASPECT_STENCIL_BIT)))
Example #2
0
class Tag(NameMixin, CreatedAtMixin, OrderedMixin, LikeMixin, IconMixin):
    TARGET_TYPE = IntFlag('Tag.TARGET_TYPE', 'FOLDER RESOURCE SKILL')
    ANY_TARGET = TARGET_TYPE.FOLDER | TARGET_TYPE.RESOURCE | TARGET_TYPE.SKILL

    color = ColorField(
        verbose_name='Цвет',
        null=True,
        blank=True,
    )
    target_type = IntFlagField(
        verbose_name='Тип цели',
        enum=TARGET_TYPE,
        default=int(ANY_TARGET),
    )

    class Meta:
        verbose_name = 'Метка'
        verbose_name_plural = 'Метки'
        default_related_name = 'tags'

    def save(self, *args, **kwargs):
        is_new = self._state.adding
        super().save(*args, **kwargs)
        if is_new:
            self.values.create(is_default=True)
Example #3
0
 def generate_compound(name,
                       bitnames,
                       null=False,
                       sep='',
                       maxbits=None,
                       offset=0):
     for s in bitnames:
         if len(s) > 1:
             sep = '+'
             break
     nbits = {}
     s2i = dict([(s, i + offset) for i, s in enumerate(bitnames)])
     d = []
     if null:
         d.append(('null', 0))
         nbits['null'] = 0
         nbits[0] = 0
     for s in bitnames:
         v = 1 << s2i[s]
         d.append((s, v))
         nbits[s] = 1
         nbits[v] = 1
     for i in range(2, len(bitnames) + 1):
         if maxbits and i > maxbits:
             continue
         for c in combinations(bitnames, i):
             s = sep.join(c)
             j = 0
             for x in c:
                 j |= 1 << s2i[x]
             d.append((s, j))
             nbits[s] = i
             nbits[j] = i
     states = IntFlag(name, d)
     return states, nbits
Example #4
0
def create_device():
    global physical_device, render_queue_family, device

    # Device selection (use the first available)
    physical_devices = hvk.list_physical_devices(api, instance)
    physical_device = physical_devices[0]

    # Queues setup (A single graphic queue)
    queue_families = hvk.list_queue_families(api, physical_device)
    render_queue_family = next(qf for qf in queue_families if IntFlag(
        vk.QUEUE_GRAPHICS_BIT) in IntFlag(qf.properties.queue_flags))
    render_queue_create_info = hvk.queue_create_info(
        queue_family_index=render_queue_family.index, queue_count=1)

    # Device creation
    extensions = ("VK_KHR_swapchain", )
    device = hvk.create_device(api, physical_device, extensions,
                               (render_queue_create_info, ))
Example #5
0
    def generate_from_graph(name,
                            bitnames,
                            g,
                            null=True,
                            sep='',
                            maxbits=None):
        '''
        calculate the set of "contiguous" compound states with maximum
        size `maxbits` from the given graph of simple states
        '''
        # http://stackoverflow.com/questions
        # /15658245/efficiently-find-all-connected-subgraphs
        for s in bitnames:
            if len(s) > 1:
                sep = '+'
                break
        nbits = {}
        results = []
        if null:
            results.append(('null', 0))
            nbits['null'] = 0
            nbits[0] = 0
        for i, s in enumerate(bitnames):
            j = 1 << i
            results.append((s, j))
            nbits[s] = 1
            nbits[j] = 1

        def gsg(nodes, subset, neighbors):
            if not subset:
                candidates = nodes
            else:
                candidates = nodes.intersection(neighbors)
            if not candidates:
                nb = len(subset)
                if 2 <= nb <= maxbits:
                    s = sep.join([
                        bitnames[x.index]
                        for x in sorted(subset, key=lambda e: e.index)
                    ])
                    j = 0
                    for x in subset:
                        j |= 1 << x.index
                    results.append((s, j))
                    nbits[s] = nb
                    nbits[j] = nb
            else:
                n = next(iter(candidates))
                sn = set([n])
                nmsn = nodes - sn
                gsg(nmsn, subset, neighbors)
                gsg(nmsn, subset.union(sn), neighbors.union(n.neighbors()))

        gsg(set(g.vs()), set(), set())
        states = IntFlag(name, results)
        return states, nbits
Example #6
0
 def generate_simple(name, bitnames, null=False, offset=0):
     flags = []
     if null:
         flags.append(('null', 0))
     for i, s in enumerate(bitnames):
         i += offset
         flags.append((s, 1 << i))
     states = IntFlag(name, flags)
     nbits = {}
     for state in states:
         nbits[state.name] = 1
         nbits[state.value] = 1
     return states, nbits
Example #7
0
 def __init__(self, name, msgdef, options=None):
     self.size = types['u32'].size
     self.name = name
     self.enumtype = 'u32'
     self.msgdef = msgdef
     e_hash = {}
     for f in msgdef:
         if type(f) is dict and 'enumtype' in f:
             if f['enumtype'] != 'u32':
                 self.size = types[f['enumtype']].size
                 self.enumtype = f['enumtype']
             continue
         ename, evalue = f
         e_hash[ename] = evalue
     self.enum = IntFlag(name, e_hash)
     types[name] = self
     class_types[name] = VPPEnumType
     self.options = options
Example #8
0
from enum import IntFlag

ResetLevels = IntFlag('ResetLevels', 'all allButID allButIDDR')
##############################################
# The MIT License (MIT)
# Copyright (c) 2016 Kevin Walchko
# see LICENSE for full details
##############################################
import attr
from math import cos, sin, pi, atan2, asin, sqrt
from squaternion import Quaternion
from ins_nav.utils import rad2deg
from ins_nav.utils import normalize3
from enum import IntFlag

Angle = IntFlag("Angle", "degrees radians quaternion")


@attr.s(slots=True)
class TiltCompensatedCompass(object):
    """
    A tilt compensated compass is basically just taking the magnetometer
    readings and adjusting them based of how the sensor is oriented (tilted).
    We use the accelerometer to determine the orientation relative to the
    ground. Obviously, if the sensor is under some sort of gravity loading,
    say movng fast (falling), then this won't work correctly.

    Also, the in sensor inputs are expected to have already been adjusted
    for biases and other issues (hard/soft iron errors).
    """

    angle_units = attr.ib(default=Angle.degrees)

    # def __init__(self, angle_units=Angle.degrees):
Example #10
0
class FtdiEeprom:
    """FTDI EEPROM management
    """

    _PROPS = namedtuple('PROPS', 'size user dynoff')
    """Properties for each FTDI device release."""

    _PROPERTIES = {
        0x0200: _PROPS(0, None, 0x94),     # FT232AM
        0x0400: _PROPS(256, 0x14, 0x94),   # FT232BM
        0x0500: _PROPS(256, 0x16, 0x96),   # FT2232D
        0x0600: _PROPS(128, None, 0x98),   # FT232R
        0x0700: _PROPS(256, 0x1A, 0x9A),   # FT2232H
        0x0800: _PROPS(256, 0x1A, 0x9A),   # FT4232H
        0x0900: _PROPS(256, 0x1A, 0xA0),   # FT232H
        0x1000: _PROPS(1024, 0x1A, 0xA0),  # FT230X/FT231X/FT234X
    }
    """EEPROM properties."""


    CBUS = IntEnum('CBUS',
                   'TXDEN PWREN RXLED TXLED TXRXLED SLEEP CLK48 CLK24 CLK12 '
                   'CLK6 IOMODE BB_WR BB_R', start=0)
    """Alternate features for legacy FT232R devices."""

    CBUSH = IntEnum('CBUSH',
                    'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                    'IOMODE TXDEN CLK30 CLK15 CLK7_5', start=0)
    """Alternate features for FT232H/FT2232H/FT4232H devices."""

    CBUSX = IntEnum('CBUSX',
                    'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                    'IOMODE TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_DETECT_NEG '
                    'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIME_STAMP AWAKE',
                    start=0)
    """Alternate features for FT230X devices."""

    INVERT = IntFlag('INVERT', 'TXD RXD RTS CTS DTR DSR DCD RI')
    """Inversion flags for FT232R devices."""

    CHANNEL = IntFlag('CHANNEL', 'FIFO OPTO CPU FT128 RS485')
    """Alternate port mode."""

    DRIVE = IntEnum('DRIVE',
                    'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS')
    """Driver options for I/O pins."""

    CFG1 = IntFlag('CFG1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 '
                            'HIGH_CURRENTDRIVE _20 _40 SUSPEND_DBUS7')
    """Configuration bits stored @ 0x01."""

    VAR_STRINGS = ('manufacturer', 'product', 'serial')
    """EEPROM strings with variable length."""

    def __init__(self):
        self.log = getLogger('pyftdi.eeprom')
        self._ftdi = Ftdi()
        self._eeprom = bytearray()
        self._dev_ver = 0
        self._valid = False
        self._config = OrderedDict()
        self._dirty = set()

    def __getattr__(self, name):
        if name in self._config:
            return self._config[name]
        raise AttributeError('No such attribute: %s' % name)

    def open(self, device: Union[str, UsbDevice],
             ignore: bool = False) -> None:
        """Open a new connection to the FTDI USB device.

           :param device: the device URL or a USB device instance.
           :param ignore: whether to ignore existing content
        """
        if self._ftdi.is_connected:
            raise FtdiError('Already open')
        if isinstance(device, str):
            self._ftdi.open_from_url(device)
        else:
            self._ftdi.open_from_device(device)
        if not ignore:
            self._read_eeprom()
            if self._valid:
                self._decode_eeprom()

    def close(self) -> None:
        """Close the current connection to the FTDI USB device,
        """
        if self._ftdi.is_connected:
            self._ftdi.close()
            self._eeprom = bytearray()
            self._dev_ver = 0
            self._config.clear()

    def connect(self, ftdi: Ftdi, ignore: bool = False) -> None:
        """Connect a FTDI EEPROM to an existing Ftdi instance.

           :param ftdi: the Ftdi instance to use
           :param ignore: whether to ignore existing content
        """
        self._ftdi = ftdi
        self._eeprom = bytearray()
        self._dev_ver = 0
        self._valid = False
        self._config = OrderedDict()
        self._dirty = set()
        if not ignore:
            self._read_eeprom()
            if self._valid:
                self._decode_eeprom()

    @property
    def device_version(self) -> int:
        """Report the version of the FTDI device.

           :return: the release
        """
        if not self._dev_ver:
            if not self._ftdi.is_connected:
                raise FtdiError('Not connected')
            self._dev_ver = self._ftdi.device_version
        return self._dev_ver

    @property
    def size(self) -> int:
        """Report the EEPROM size.

           The physical EEPROM size may be greater.

           :return: the size in bytes
        """
        try:
            eeprom_size = self._PROPERTIES[self.device_version].size
        except (AttributeError, KeyError):
            raise FtdiError('No EEPROM')
        return eeprom_size

    @property
    def data(self) -> bytes:
        """Returns the content of the EEPROM.

           :return: the content as bytes.
        """
        self._sync_eeprom()
        return bytes(self._eeprom)

    @property
    def properties(self) ->  Set[str]:
        """Returns the supported properties for the current device.

           :return: the supported properies.
        """
        props = set(self._config.keys())
        props -= set(self.VAR_STRINGS)
        return props

    @property
    def is_empty(self) -> bool:
        """Reports whether the EEPROM has been erased, or no EEPROM is
           connected to the FTDI EEPROM port.

           :return: True if no content is detected
        """
        if len(self._eeprom) != self._PROPERTIES[self.device_version].size:
            return False
        for byte in self._eeprom:
            if byte != 0xFF:
                return False
        return True

    @property
    def cbus_pins(self) -> List[int]:
        """Return the list of CBUS pins configured as GPIO, if any

           :return: list of CBUS pins
        """
        pins = [pin for pin in range(0, 10)
                if self._config.get('cbus_func_%d' % pin, '') == 'IOMODE']
        return pins

    @property
    def cbus_mask(self) -> int:
        """Return the bitmask of CBUS pins configured as GPIO.

           The bitmap contains four bits, ordered in natural order.

           :return: CBUS mask
        """
        if self.device_version == 0x900:  # FT232H
            cbus = [5, 6, 8, 9]
        else:
            cbus = list(range(4))
        mask = 0
        for bix, pin in enumerate(cbus):
            if self._config.get('cbus_func_%d' % pin, '') == 'IOMODE':
                mask |= 1 << bix
        return mask

    def save_config(self, file: TextIO) -> None:
        """Save the EEPROM content as an INI stream.

           :param file: output stream
        """
        self._sync_eeprom()
        cfg = ConfigParser()
        cfg.add_section('values')
        for name, value in self._config.items():
            cfg.set('values', name, str(value))
        cfg.add_section('raw')
        length = 16
        for i in range(0, len(self._eeprom), length):
            chunk = self._eeprom[i:i+length]
            hexa = hexlify(chunk).decode()
            cfg.set('raw', '@%02x' % i, hexa)
        cfg.write(file)

    def set_serial_number(self, serial: str) -> None:
        """Define a new serial number."""
        self._validate_string(serial)
        self._update_var_string('serial', serial)
        self.set_property('has_serial', True)

    def set_manufacturer_name(self, manufacturer: str) -> None:
        """Define a new manufacturer string."""
        self._validate_string(manufacturer)
        self._update_var_string('manufacturer', manufacturer)

    def set_product_name(self, product: str) -> None:
        """Define a new product name."""
        self._validate_string(product)
        self._update_var_string('product', product)

    def set_property(self, name: str, value: Union[str, int, bool],
                     out: Optional[TextIO] = None) -> None:
        """Change the value of a stored property.

           :see: :py:meth:`properties` for a list of valid property names.
                 Note that for now, only a small subset of properties can be
                 changed.
           :param name: the property to change
           :param value: the new value (supported values depend on property)
           :param out: optional output stream to report hints
        """
        mobj = match(r'cbus_func_(\d)', name)
        if mobj:
            if not isinstance(value, str):
                raise ValueError("'%s' should be specified as a string" % name)
            self._set_cbus_func(int(mobj.group(1)), value, out)
            self._dirty.add(name)
            return
        hwords = {
            'vendor_id': 0x02,
            'product_id': 0x04,
            'type': 0x06,
            'usb_version': 0x0c
        }
        if name in hwords:
            val = to_int(value)
            if not 0 <= val <= 0xFFFF:
                raise ValueError('Invalid value for %s' % name)
            offset = hwords[name]
            self._eeprom[offset:offset+2] = spack('<H', val)
            return
        confs = {
            'remote_wakeup': (0, 5),
            'self_powered': (0, 6),
            'in_isochronous': (2, 0),
            'out_isochronous': (2, 1),
            'suspend_pull_down': (2, 2),
            'has_serial': (2, 3),
            'has_usb_version': (2, 4),
        }
        if name in confs:
            val = to_bool(value, permissive=False, allow_int=True)
            offset, bit = confs[name]
            mask = 1 << bit
            if val:
                self._eeprom[0x08+offset] |= mask
            else:
                self._eeprom[0x0a+offset] &= ~mask
            return
        if name == 'power_max':
            val = to_int(value) >> 1
            self._eeprom[0x09] = val
            return
        if name in self.properties:
            raise NotImplementedError("Change to '%s' is not yet supported" %
                                      name)
        raise ValueError("Unknown property '%s'" % name)

    def erase(self) -> None:
        """Erase the whole EEPROM."""
        self._eeprom = bytearray([0x00] * self.size)
        self._config.clear()

    def initialize(self) -> None:
        """Initialize the EEPROM with some default sensible values.
        """
        dev_ver = self.device_version
        dev_name = Ftdi.DEVICE_NAMES[dev_ver]
        vid = Ftdi.FTDI_VENDOR
        pid = Ftdi.PRODUCT_IDS[vid][dev_name]
        self.set_manufacturer_name('FTDI')
        self.set_product_name(dev_name.upper())
        sernum = ''.join([chr(randint(ord('A'), ord('Z'))) for _ in range(5)])
        self.set_serial_number('FT%d%s' % (randint(0, 9), sernum))
        self.set_property('vendor_id', vid)
        self.set_property('product_id', pid)
        self.set_property('type', dev_ver)
        self.set_property('usb_version', 0x200)
        self.set_property('power_max', 150)
        self._sync_eeprom()

    def sync(self) -> None:
        """Force re-evaluation of configuration after some changes.

           This API is not useful for regular usage, but might help for testing
           when the EEPROM does not go through a full save/load cycle
        """
        self._sync_eeprom()

    def dump_config(self, file: Optional[BinaryIO] = None) -> None:
        """Dump the configuration to a file.

           :param file: the output file, default to stdout
        """
        if self._dirty:
            self._decode_eeprom()
        for name, value in self._config.items():
            print('%s: %s' % (name, value), file=file or sys.stdout)

    def commit(self, dry_run: bool = True) -> bool:
        """Commit any changes to the EEPROM.

           :param dry_run: log what should be written, do not actually
                           change the EEPROM content

           :return: True if some changes have been committed to the EEPROM
        """
        if not self._dirty:
            self.log.info('No change to commit')
            return False
        self.log.info('Changes to commit: %s', ', '.join(sorted(self._dirty)))
        self._sync_eeprom()
        self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run)
        return dry_run

    @classmethod
    def _validate_string(cls, string):
        for invchr in ':/':
            # do not accept characters which are interpreted as URL seperators
            if invchr in string:
                raise ValueError("Invalid character '%s' in string" % invchr)

    def _update_var_string(self, name: str, value: str) -> None:
        if name not in self.VAR_STRINGS:
            raise ValueError('%s is not a variable string' % name)
        try:
            if value == self._config[name]:
                return
        except KeyError:
            # not yet defined
            pass
        self._config[name] = value
        self._dirty.add(name)

    def _generate_var_strings(self, fill=True) -> None:
        stream = bytearray()
        dynpos = self._PROPERTIES[self.device_version].dynoff
        data_pos = dynpos
        tbl_pos = 0x0e
        for name in self.VAR_STRINGS:
            try:
                ustr = self._config[name].encode('utf-16le')
            except KeyError:
                ustr = ''
            length = len(ustr)+2
            stream.append(length)
            stream.append(0x03)  # string descriptor
            stream.extend(ustr)
            self._eeprom[tbl_pos] = data_pos
            tbl_pos += 1
            self._eeprom[tbl_pos] = length
            tbl_pos += 1
            data_pos += length
        self._eeprom[dynpos:dynpos+len(stream)] = stream
        crc_size = scalc('<H')
        if fill:
            mtp = self._ftdi.device_version == 0x1000
            crc_pos = 0x100 if mtp else len(self._eeprom)
            crc_pos -= crc_size
            rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size
            self._eeprom[dynpos+len(stream):crc_pos] = bytes(rem)

    def _sync_eeprom(self):
        if not self._dirty:
            return
        if any([x in self._dirty for x in self.VAR_STRINGS]):
            self._generate_var_strings()
            for varstr in self.VAR_STRINGS:
                self._dirty.discard(varstr)
        self._update_crc()
        self._decode_eeprom()
        self._dirty.clear()

    def _compute_crc(self, check=False):
        mtp = self._ftdi.device_version == 0x1000
        crc_pos = 0x100 if mtp else len(self._eeprom)
        crc_size = scalc('<H')
        if not check:
            # check mode: add CRC itself, so that result should be zero
            crc_pos -= crc_size
        crc = self._ftdi.calc_eeprom_checksum(self._eeprom[:crc_pos])
        return crc, crc_pos, crc_size

    def _update_crc(self):
        crc, crc_pos, crc_size = self._compute_crc()
        self._eeprom[crc_pos:crc_pos+crc_size] = spack('<H', crc)

    def _read_eeprom(self):
        buf = self._ftdi.read_eeprom(0, eeprom_size=self.size)
        self._eeprom = bytearray(buf)
        crc = self._compute_crc(True)[0]
        if crc:
            if self.is_empty:
                self.log.info('No EEPROM or EEPROM erased')
            else:
                self.log.error('Invalid CRC or EEPROM content')
        self._valid = not bool(crc)

    def _decode_eeprom(self):
        cfg = self._config
        cfg.clear()
        cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0])
        cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0])
        cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0])
        power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b])
        cfg['self_powered'] = bool(power_supply & (1 << 6))
        cfg['remote_wakeup'] = bool(power_supply & (1 << 5))
        cfg['power_max'] = power_max << 1
        cfg['has_usb_version'] = bool(conf & (1 << 4))
        cfg['has_serial'] = bool(conf & (1 << 3))
        cfg['suspend_pull_down'] = bool(conf & (1 << 2))
        cfg['out_isochronous'] = bool(conf & (1 << 1))
        cfg['in_isochronous'] = bool(conf & (1 << 0))
        cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0])
        cfg['manufacturer'] = self._decode_string(0x0e)
        cfg['product'] = self._decode_string(0x10)
        cfg['serial'] = self._decode_string(0x12)
        try:
            name = Ftdi.DEVICE_NAMES[cfg['type']]
            func = getattr(self, '_decode_%s' % name[2:])
        except (KeyError, AttributeError):
            pass
        else:
            func()

    def _decode_string(self, offset):
        str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset+2])
        if str_size:
            str_offset &= self.size - 1
            str_size -= scalc('<H')
            str_offset += scalc('<H')
            manufacturer = self._eeprom[str_offset:str_offset+str_size]
            return manufacturer.decode('utf16', errors='ignore')
        return ''

    def _set_cbus_func(self, cpin: int, value: str,
                       out: Optional[TextIO]) -> None:
        cmap = {0x600: (self.CBUS, 5, 0x14, 4),    # FT232R
                0x900: (self.CBUSH, 10, 0x18, 4),  # FT232H
                0x1000: (self.CBUSX, 4, 0x1A, 8)}  # FT230X/FT231X/FT234X
        try:
            cbus, count, offset, width = cmap[self.device_version]
        except KeyError:
            raise ValueError('This property is not supported on this device')
        if value == '?' and out:
            print(', '.join(sorted([item.name for item in cbus])), file=out)
            return
        if not 0 <= cpin < count:
            raise ValueError("Unsupported CBUS pin '%d'" % cpin)
        try:
            code = cbus[value.upper()]
        except KeyError:
            raise ValueError("CBUS pin %d does not have function '%s'" %
                             (cpin, value))
        addr = offset + (cpin*width)//8
        if width == 4:
            bitoff = 4 if cpin & 0x1 else 0
            mask = 0x0F << bitoff
        else:
            bitoff = 0
            mask = 0xFF
        old = self._eeprom[addr]
        self._eeprom[addr] &= ~mask
        self._eeprom[addr] |= code << bitoff
        self.log.debug('Cpin %d, addr 0x%02x, value 0x%02x->0x%02x',
                       cpin, addr, old, self._eeprom[addr])

    def _decode_230x(self):
        cfg = self._config
        misc, = sunpack('<H', self._eeprom[0x00:0x02])
        cfg['channel_a_driver'] = 'VCP' if misc & (1 << 7) else 'D2XX'
        for bit in self.INVERT:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit)
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        value = self._eeprom[0x0c]
        for grp in range(2):
            conf = value &0xF
            cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive)
            cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT
            cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW
            value >>= 4
        for bix in range(4):
            value = self._eeprom[0x1A + bix]
            cfg['cbus_func_%d' % bix] = self.CBUSX(value).name
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232h(self):
        cfg = self._config
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = cfg0 & 0x0F
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else 'D2XX'
        cfg['clock_polarity'] = 'high' if (cfg1 & self.CFG1.CLK_IDLE_STATE) \
                                else 'low'
        cfg['lsb_data'] = bool(cfg1 & self.CFG1.DATA_LSB)
        cfg['flow_control'] = 'on' if (cfg1 & self.CFG1.FLOW_CONTROL) \
                              else 'off'
        cfg['powersave'] = bool(cfg1 & self.DRIVE.PWRSAVE_DIS)
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        for grp in range(2):
            conf = self._eeprom[0x0c+grp]
            cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive)
            cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT
            cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW
        for bix in range(5):
            value = self._eeprom[0x18 + bix]
            low, high = value & 0x0F, value >> 4
            cfg['cbus_func_%d' % ((2*bix)+0)] = self.CBUSH(low).name
            cfg['cbus_func_%d' % ((2*bix)+1)] = self.CBUSH(high).name
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232r(self):
        cfg = self._config
        cfg0 = self._eeprom[0x00]
        cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else ''
        cfg['high_current'] = bool(~cfg0 & (1 << 2))
        cfg['external_oscillator'] = cfg0 & 0x02
        for bit in self.INVERT:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit)
        bix = 0
        while True:
            value = self._eeprom[0x14 + bix]
            low, high = value & 0x0F, value >> 4
            cfg['cbus_func_%d' % ((2*bix)+0)] = self.CBUS(low).name
            if bix == 2:
                break
            cfg['cbus_func_%d' % ((2*bix)+1)] = self.CBUS(high).name
            bix += 1

    def _decode_2232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = self.CHANNEL(cfg0 & 0x7).name or 'UART'
        cfg['channel_b_type'] = self.CHANNEL(cfg1 & 0x7).name or 'UART'
        cfg['suspend_dbus7'] = cfg1 & self.CFG1.SUSPEND_DBUS7

    def _decode_4232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else 'D2XX'
        cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else 'D2XX'
        conf = self._eeprom[0x0B]
        rs485 = self.CHANNEL.RS485
        for chix in range(4):
            cfg['channel_%x_rs485' % (0xa+chix)] = bool(conf & (rs485 << chix))

    def _decode_x232h(self, cfg):
        # common code for2232h and 4232h
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else 'D2XX'
        cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else 'D2XX'
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        for bix in range(4):
            if not bix & 1:
                val = self._eeprom[0x0c + bix//2]
            else:
                val >>= 4
            cfg['group_%d_drive' % bix] = bool(val & max_drive)
            cfg['group_%d_schmitt' % bix] = bool(val & self.DRIVE.SCHMITT)
            cfg['group_%d_slew' % bix] = bool(val & self.DRIVE.SLOW_SLEW)
        cfg['chip'] = Hex2Int(self._eeprom[0x18])
Example #11
0
]
__all__.extend(os._get_exports_list(_socket))

# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for
# nicer string representations.
# Note that _socket only knows about the integer values. The public interface
# in this module understands the enums and translates them back from integers
# where needed (e.g. .family property of a socket object).

IntEnum._convert_("AddressFamily", __name__,
                  lambda C: C.isupper() and C.startswith("AF_"))

IntEnum._convert_("SocketKind", __name__,
                  lambda C: C.isupper() and C.startswith("SOCK_"))

IntFlag._convert_("MsgFlag", __name__,
                  lambda C: C.isupper() and C.startswith("MSG_"))

IntFlag._convert_("AddressInfo", __name__,
                  lambda C: C.isupper() and C.startswith("AI_"))

_LOCALHOST = "127.0.0.1"
_LOCALHOST_V6 = "::1"


def _intenum_converter(value, enum_klass):
    """Convert a numeric family value to an IntEnum member.

    If it's not a known member, return the numeric value itself.
    """
    try:
        return enum_klass(value)
Example #12
0
File: link.py Project: mlaves/dh
import attr
from collections import namedtuple
from enum import IntFlag
import numpy as np  # type: ignore
np.set_printoptions(suppress=True)
from colorama import Fore

JointType = IntFlag('JointType',
                    'revolute prismatic revolute_theda revolute_alpha')
mdh_params = namedtuple("mdh_params", "alpha a theta d ")

from math import pi
rad2deg = 180 / pi
deg2rad = pi / 180


@attr.s(slots=True)
class RevoluteLink:
    """
    RevoluteLink about theta. All other parameters (alpha, a, d) are fixed and
    cannot be changed once the link is created.
    """
    _alpha = attr.ib()
    _a = attr.ib()
    theta = attr.ib()
    _d = attr.ib()
    min = attr.ib(default=-np.pi / 2)
    max = attr.ib(default=np.pi / 2)

    @max.validator
    def max_check(self, attribute, value):
Example #13
0
 def __new__(metacls, name, bases, d):
     flags = [(i.name, i.value) for i in AmpelFlags]
     for k, v in d.items():
         if not k.endswith('__'):
             flags.append((k, v))
     return IntFlag(name, flags, module=d['__module__'])
Example #14
0
from enum import IntFlag
from itertools import chain

from msdsalgs.security_types.access_mask import AccessMask
from msdsalgs.utils import Mask


# TODO: Add standard user rights?
class RegsamFlag(IntFlag):
    KEY_QUERY_VALUE = 0x00000001
    KEY_SET_VALUE = 0x00000002
    KEY_CREATE_SUB_KEY = 0x00000004
    KEY_ENUMERATE_SUB_KEYS = 0x00000008
    KEY_CREATE_LINK = 0x00000020
    KEY_WOW64_64KEY = 0x00000100
    KEY_WOW64_32KEY = 0x00000200


Regsam = Mask.make_class(int_flag_class=IntFlag('Regsam', (
    (enum_entry.name, enum_entry.value)
    for enum_entry in chain(AccessMask, RegsamFlag))))
Example #15
0
 def __str__(self):
     """Provides just the name representation of enum."""
     return IntFlag.__str__(self)[len(self.__class__.__name__) + 1:]
Example #16
0
class FtdiEeprom:
    """FTDI EEPROM management
    """

    _PROPS = namedtuple('PROPS', 'size user dynoff')
    """Properties for each FTDI device release."""

    _PROPERTIES = {
        0x0200: _PROPS(0, None, 0x94),  # FT232AM
        0x0400: _PROPS(256, 0x14, 0x94),  # FT232BM
        0x0500: _PROPS(256, 0x16, 0x96),  # FT2232D
        0x0600: _PROPS(128, None, 0x98),  # FT232R
        0x0700: _PROPS(256, 0x1A, 0x9A),  # FT2232H
        0x0800: _PROPS(256, 0x1A, 0x9A),  # FT4232H
        0x0900: _PROPS(256, 0x1A, 0xA0),  # FT232H
        0x1000: _PROPS(256, 0x1A, 0xA0),  # FT230X
    }
    """EEPROM properties."""

    _CBUS = IntEnum('CBUS',
                    'TXDEN PWREN RXLED TXLED TXRXLED SLEEP CLK48 CLK24 CLK12 '
                    'CLK6 IOMODE BB_WR BB_R',
                    start=0)
    """Alternate features for legacy FT232R devices."""

    _CBUSH = IntEnum('CBUSH',
                     'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                     'IOMODE TXDEN CLK30 CLK15 CLK7_5',
                     start=0)
    """Alternate features for FT232H/FT2232H/FT4232H devices."""

    _CBUSX = IntEnum('CBUSX',
                     'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                     'IOMODE TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_DETECT_NEG '
                     'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIME_STAMP AWAKE',
                     start=0)
    """Alternate features for FT230X devices."""

    _INVERT = IntFlag('INVERT', 'TXD RXD RTS CTS DTR DSR DCD RI')
    """Inversion flags for FT232R devices."""

    _CHANNEL = IntFlag('CHANNEL', 'FIFO OPTO CPU FT128 RS485')
    """Alternate port mode."""

    _DRIVE = IntEnum('DRIVE',
                     'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS')
    """Driver options for I/O pins."""

    _CFG1 = IntFlag(
        'CFG1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 '
        'HIGH_CURRENT_DRIVE _20 _40 SUSPEND_DBUS7')
    """Configuration bits stored @ 0x01."""

    VAR_STRINGS = ('manufacturer', 'product', 'serial')
    """EEPROM strings with variable length."""
    def __init__(self):
        self.log = getLogger('pyftdi.eeprom')
        self._ftdi = Ftdi()
        self._eeprom = bytearray()
        self._dev_ver = 0
        self._valid = False
        self._config = OrderedDict()
        self._dirty = set()

    def __getattr__(self, name):
        if name in self._config:
            return self._config[name]
        raise AttributeError('No such attribute: %s' % name)

    def open(self, device: Union[str, UsbDevice]) -> None:
        """Open a new connection to the FTDI USB device.

           :param device: the device URL or a USB device instance.
        """
        if self._ftdi.is_connected:
            raise FtdiError('Already open')
        if isinstance(device, str):
            self._ftdi.open_from_url(device)
        else:
            self._ftdi.open_from_device(device)
        self._read_eeprom()
        if self._valid:
            self._decode_eeprom()

    def close(self) -> None:
        """Close the current connection to the FTDI USB device,
        """
        if self._ftdi.is_connected:
            self._ftdi.close()
            self._eeprom = bytearray()
            self._dev_ver = 0
            self._config.clear()

    @property
    def device_version(self) -> int:
        """Report the version of the FTDI device.

           :return: the release
        """
        if not self._dev_ver:
            if not self._ftdi.is_connected:
                raise FtdiError('Not connected')
            self._dev_ver = self._ftdi.device_version
        return self._dev_ver

    @property
    def size(self) -> int:
        """Report the EEPROM size.

           The physical EEPROM size may be greater.

           :return: the size in bytes
        """
        try:
            eeprom_size = self._PROPERTIES[self.device_version].size
        except (AttributeError, KeyError):
            raise FtdiError('No EEPROM')
        return eeprom_size

    @property
    def data(self) -> bytes:
        """Returns the content of the EEPROM.

           :return: the content as bytes.
        """
        return bytes(self._eeprom)

    @property
    def is_empty(self) -> bool:
        """Reports whether the EEPROM has been erased, or no EEPROM is
           connected to the FTDI EEPROM port.

           :return: True if no content is detected
        """
        if len(self._eeprom) != self._PROPERTIES[self.device_version].size:
            return False
        for byte in self._eeprom:
            if byte != 0xFF:
                return False
        return True

    def save_config(self, file: TextIO) -> None:
        """Save the EEPROM content as an INI stream.

           :param file: output stream
        """
        cfg = ConfigParser()
        cfg.add_section('values')
        for name, value in self._config.items():
            cfg.set('values', name, str(value))
        cfg.add_section('raw')
        length = 16
        for i in range(0, len(self._eeprom), length):
            chunk = self._eeprom[i:i + length]
            hexa = hexlify(chunk).decode()
            cfg.set('raw', '@%02x' % i, hexa)
        cfg.write(file)

    def set_serial_number(self, serial: str) -> None:
        """Define a new serial number."""
        self._update_var_string('serial', serial)

    def set_manufacturer_name(self, manufacturer: str) -> None:
        """Define a new manufacturer string."""
        self._update_var_string('manufacturer', manufacturer)

    def set_product_name(self, product: str) -> None:
        """Define a new product name."""
        self._update_var_string('product', product)

    def erase(self) -> None:
        """Erase the whole EEPROM."""
        self._eeprom = bytearray([0xFF] * self.size)
        self._config.clear()

    def dump_config(self, file: Optional[BinaryIO] = None) -> None:
        """Dump the configuration to a file.

           :param file: the output file, default to stdout
        """
        for name, value in self._config.items():
            print('%s: %s' % (name, value), file=file or stdout)

    def commit(self, dry_run: bool = True) -> bool:
        """Commit any changes to the EEPROM.

           :param dry_run: log what should be written, do not actually
                           change the EEPROM content

           :return: True if some changes have been committed to the EEPROM
        """
        if not self._dirty:
            self.log.info('No change to commit')
            return False
        self.log.info('Changes to commit: %s', ', '.join(sorted(self._dirty)))
        if any([x in self._dirty for x in self.VAR_STRINGS]):
            self._generate_var_strings()
        self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run)
        return dry_run

    def _update_var_string(self, name: str, value: str) -> None:
        if name not in self.VAR_STRINGS:
            raise ValueError('%s is not a variable string' % name)
        if value == self._config[name]:
            return
        self._config[name] = value
        self._dirty.add(name)

    def _generate_var_strings(self, fill=True) -> None:
        stream = bytearray()
        dynpos = self._PROPERTIES[self.device_version].dynoff
        data_pos = dynpos
        tbl_pos = 0x0e
        for name in self.VAR_STRINGS:
            ustr = self._config[name].encode('utf-16le')
            length = len(ustr) + 2
            stream.append(length)
            stream.append(0x03)  # no idea what this constant means
            stream.extend(ustr)
            self._eeprom[tbl_pos] = data_pos
            tbl_pos += 1
            self._eeprom[tbl_pos] = length
            tbl_pos += 1
            data_pos += length
        self._eeprom[dynpos:dynpos + len(stream)] = stream
        crc_size = scalc('<H')
        if fill:
            rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size
            self._eeprom[dynpos + len(stream):-crc_size] = bytes(rem)
        crc = self._ftdi.calc_eeprom_checksum(self._eeprom[:-crc_size])
        self._eeprom[-crc_size:] = spack('<H', crc)

    def _read_eeprom(self):
        self._eeprom = bytearray(
            self._ftdi.read_eeprom(0, eeprom_size=self.size))
        crc = self._ftdi.calc_eeprom_checksum(self._eeprom)
        if crc:
            if self.is_empty:
                self.log.info('No EEPROM or EEPROM erased')
            else:
                self.log.error('Invalid CRC or EEPROM content')
        self._valid = not bool(crc)

    def _decode_eeprom(self):
        cfg = self._config
        cfg.clear()
        cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0])
        cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0])
        cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0])
        power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b])
        cfg['self_powered'] = bool(power_supply & (1 << 6))
        cfg['remote_wakeup'] = bool(power_supply & (1 << 5))
        cfg['power_max'] = power_max << 1
        cfg['has_usb_version'] = bool(conf & (1 << 4))
        cfg['has_serial'] = bool(conf & (1 << 3))
        cfg['suspend_pull_down'] = bool(conf & (1 << 2))
        cfg['out_isochronous'] = bool(conf & (1 << 1))
        cfg['in_isochronous'] = bool(conf & (1 << 0))
        cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0])
        cfg['manufacturer'] = self._decode_string(0x0e)
        cfg['product'] = self._decode_string(0x10)
        cfg['serial'] = self._decode_string(0x12)

        try:
            name = Ftdi.DEVICE_NAMES[cfg['type']]
            func = getattr(self, '_decode_%s' % name[2:])
        except (KeyError, AttributeError):
            pass
        else:
            func()

    def _decode_string(self, offset):
        str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset + 2])
        if str_size:
            str_offset &= self.size - 1
            str_size -= scalc('<H')
            str_offset += scalc('<H')
            manufacturer = self._eeprom[str_offset:str_offset + str_size]
            return manufacturer.decode('utf16', errors='ignore')
        return ''

    def _decode_230x(self):
        cfg = self._config
        cfg['channel_a_driver'] = 'VCP'
        for bit in self.INVERT:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit)
        max_drive = self._DRIVE.LOW | self._DRIVE.HIGH
        value = self._eeprom[0x0c]
        for grp in range(2):
            conf = value & 0xF
            cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive)
            cfg['group_%d_schmitt' % grp] = conf & self._DRIVE.SCHMITT
            cfg['group_%d_slew' % grp] = conf & self._DRIVE.SLOW_SLEW
            value >>= 4
        for bix in range(4):
            value = self._eeprom[0x1A + bix]
            cfg['cbus_func_%d' % bix] = self._CBUSX(value).name
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232h(self):
        cfg = self._config
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = cfg0 & 0x0F
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else ''
        cfg['clock_polarity'] = 'high' if (cfg1 & self._CFG1.CLK_IDLE_STATE) \
                                else 'low'
        cfg['lsb_data'] = bool(cfg1 & self._CFG1.DATA_LSB)
        cfg['flow_control'] = 'on' if (cfg1 & self._CFG1.FLOW_CONTROL) \
                              else 'off'
        cfg['powersave'] = bool(cfg1 & self._DRIVE.PWRSAVE_DIS)
        max_drive = self._DRIVE.LOW | self._DRIVE.HIGH
        for grp in range(2):
            conf = self._eeprom[0x0c + grp]
            cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive)
            cfg['group_%d_schmitt' % grp] = conf & self._DRIVE.SCHMITT
            cfg['group_%d_slew' % grp] = conf & self._DRIVE.SLOW_SLEW
        for bix in range(5):
            value = self._eeprom[0x18 + bix]
            low, high = value & 0x0F, value >> 4
            cfg['cbus_func_%d' % ((2 * bix) + 0)] = self._CBUSH(low).name
            cfg['cbus_func_%d' % ((2 * bix) + 1)] = self._CBUSH(high).name
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232r(self):
        cfg = self._config
        cfg0 = self._eeprom[0x00]
        cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else ''
        cfg['high_current'] = bool(~cfg0 & (1 << 2))
        cfg['external_oscillator'] = cfg0 & 0x02
        for bit in self.INVERT:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.INVERT(bit).name] = bool(value & bit)
        bix = 0
        while True:
            value = self._eeprom[0x14 + bix]
            low, high = value & 0x0F, value >> 4
            cfg['cbus_func_%d' % ((2 * bix) + 0)] = self._CBUS(low).name
            if bix == 2:
                break
            cfg['cbus_func_%d' % ((2 * bix) + 1)] = self._CBUS(high).name
            bix += 1

    def _decode_2232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = self._CHANNEL(cfg0 & 0x7).name or 'UART'
        cfg['channel_b_type'] = self._CHANNEL(cfg1 & 0x7).name or 'UART'
        cfg['suspend_dbus7'] = cfg1 & self._CFG1.SUSPEND_DBUS7

    def _decode_4232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else ''
        cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else ''
        conf = self._eeprom[0x0B]
        rs485 = self._CHANNEL.RS485
        for chix in range(4):
            cfg['channel_%x_rs485' % (0xa + chix)] = bool(conf
                                                          & (rs485 << chix))

    def _decode_x232h(self, cfg):
        # common code for2232h and 4232h
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else ''
        cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else ''
        max_drive = self._DRIVE.LOW | self._DRIVE.HIGH
        for bix in range(4):
            if not bix & 1:
                val = self._eeprom[0x0c + bix // 2]
            else:
                val >>= 4
            cfg['group_%d_drive' % bix] = bool(val & max_drive)
            cfg['group_%d_schmitt' % bix] = bool(val & self._DRIVE.SCHMITT)
            cfg['group_%d_slew' % bix] = bool(val & self._DRIVE.SLOW_SLEW)
        cfg['chip'] = Hex2Int(self._eeprom[0x18])
Example #17
0
if TYPE_CHECKING:
    from utils.rpg.dungeon.game import Dungeon, Movement

Condition = IntFlag(
    "Condition",
    [
        "BLINDED",
        "DEAFENED",
        "GRAPPLED",
        "INCAPACITATED",
        "INVISIBLE",
        "PARALYZED",
        "PETRIFIED",
        "POISONED",
        "PRONE",
        "RESTRAINED",
        "STUNNED",
        "UNCONSCIOUS",
        "DEAD",
        "EXHAUSTED_1",
        "EXHAUSTED_2",
        "EXHAUSTED_3",
        "EXHAUSTED_4",
        "EXHAUSTED_5",
    ],
)

Relation = Enum("Relation", ["CHARMED", "FRIGHTENED"])

IMMOBILE = (Condition.GRAPPLED
import itertools
from collections import deque
from enum import IntFlag
from random import randint

import numpy as np

Dir = IntFlag("Dir", ["N", "S", "W", "E"])
DirAll = Dir.N | Dir.S | Dir.W | Dir.E


class Maze:
    def __init__(self, width, height):
        self.new_maze(width, height)

    # {'┌', '╴', '┤', '│', '┐', '╷', '╵', '┬', '└', '╶', '├', '┼', ' ', '┘', '─', '┴'}
    def __str__(self):
        def vert_str(row):
            return f"+{'+'.join('--' if x else '  ' for x in row)}+"

        def horz_str(row):
            return f"{'  '.join('|' if x else ' ' for x in row)}"

        vert_rows = [vert_str(row & Dir.N) for row in self.maze] + [
            vert_str(self.maze[-1] & Dir.S)
        ]

        horz_rows = [
            horz_str(itertools.chain(row & Dir.W, [row[-1] & Dir.E]))
            for row in self.maze
        ]
Example #19
0
##############################################
# The MIT License (MIT)
# Copyright (c) 2018 Kevin Walchko
# see LICENSE for full details
##############################################
# These are IntFlags, so you can compare them to ints. They
# start with 1 and go to N.
# ZmqType.pub == 1
# ZmqType.sub == 2
#
from enum import IntFlag

Status = IntFlag(
    'Status',
    'ok error topic_not_found core_not_found multiple_pub_error invalid_zmq_type'
)
ZmqType = IntFlag('ZmqType', 'pub sub req rep')
Example #20
0
EWOULDBLOCK = getattr(errno, "EWOULDBLOCK", 11)

__all__ = ["fromfd", "getfqdn", "create_connection", "AddressFamily", "SocketKind"]
__all__.extend(os._get_exports_list(_socket))

# Set up the socket.AF_* socket.SOCK_* constants as members of IntEnums for
# nicer string representations.
# Note that _socket only knows about the integer values. The public interface
# in this module understands the enums and translates them back from integers
# where needed (e.g. .family property of a socket object).

IntEnum._convert("AddressFamily", __name__, lambda C: C.isupper() and C.startswith("AF_"))

IntEnum._convert("SocketKind", __name__, lambda C: C.isupper() and C.startswith("SOCK_"))

IntFlag._convert("MsgFlag", __name__, lambda C: C.isupper() and C.startswith("MSG_"))

IntFlag._convert("AddressInfo", __name__, lambda C: C.isupper() and C.startswith("AI_"))

_LOCALHOST = "127.0.0.1"
_LOCALHOST_V6 = "::1"


def _intenum_converter(value, enum_klass):
    """Convert a numeric family value to an IntEnum member.

    If it's not a known member, return the numeric value itself.
    """
    try:
        return enum_klass(value)
    except ValueError:
Example #21
0
# Note that _socket only knows about the integer values. The public interface
# in this module understands the enums and translates them back from integers
# where needed (e.g. .family property of a socket object).

IntEnum._convert(
        'AddressFamily',
        __name__,
        lambda C: C.isupper() and C.startswith('AF_'))

IntEnum._convert(
        'SocketKind',
        __name__,
        lambda C: C.isupper() and C.startswith('SOCK_'))

IntFlag._convert(
        'MsgFlag',
        __name__,
        lambda C: C.isupper() and C.startswith('MSG_'))

IntFlag._convert(
        'AddressInfo',
        __name__,
        lambda C: C.isupper() and C.startswith('AI_'))

_LOCALHOST    = '127.0.0.1'
_LOCALHOST_V6 = '::1'


def _intenum_converter(value, enum_klass):
    """Convert a numeric family value to an IntEnum member.

    If it's not a known member, return the numeric value itself.
Example #22
0
class FtdiEeprom:
    """FTDI EEPROM management
    """

    _PROPS = namedtuple('PROPS', 'size user dynoff')
    """Properties for each FTDI device release.

       * size is the size in bytes of the EEPROM storage area
       * user is the size in bytes of the user storage area, if any/supported
       * dynoff is the offset in EEPROM of the first bytes to store strings
    """

    _PROPERTIES = {
        0x0200: _PROPS(0, None, 0),  # FT232AM
        0x0400: _PROPS(256, 0x14, 0x94),  # FT232BM
        0x0500: _PROPS(256, 0x16, 0x96),  # FT2232D
        0x0600: _PROPS(128, None, 0x18),  # FT232R
        0x0700: _PROPS(256, 0x1A, 0x9A),  # FT2232H
        0x0800: _PROPS(256, 0x1A, 0x9A),  # FT4232H
        0x0900: _PROPS(256, 0x1A, 0xA0),  # FT232H
        0x1000: _PROPS(1024, 0x1A, 0xA0),  # FT230X/FT231X/FT234X
    }
    """EEPROM properties."""

    CBUS = IntEnum('CBus',
                   'TXDEN PWREN TXLED RXLED TXRXLED SLEEP CLK48 CLK24 CLK12 '
                   'CLK6 GPIO BB_WR BB_RD',
                   start=0)
    """Alternate features for legacy FT232R devices."""

    CBUSH = IntEnum('CBusH',
                    'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                    'GPIO TXDEN CLK30 CLK15 CLK7_5',
                    start=0)
    """Alternate features for FT232H/FT2232H/FT4232H devices."""

    CBUSX = IntEnum('CBusX',
                    'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0 DRIVE1 '
                    'GPIO TXDEN CLK24 CLK12 CLK6 BAT_DETECT BAT_NDETECT '
                    'I2C_TXE I2C_RXF VBUS_SENSE BB_WR BB_RD TIMESTAMP AWAKE',
                    start=0)
    """Alternate features for FT230X devices."""

    UART_BITS = IntFlag('UartBits', 'TXD RXD RTS CTS DTR DSR DCD RI')
    """Inversion flags for FT232R and FT-X devices."""

    CHANNEL = IntFlag('Channel', 'FIFO OPTO CPU FT128 RS485')
    """Alternate port mode."""

    DRIVE = IntFlag('Drive',
                    'LOW HIGH SLOW_SLEW SCHMITT _10 _20 _40 PWRSAVE_DIS')
    """Driver options for I/O pins."""

    CFG1 = IntFlag(
        'Cfg1', 'CLK_IDLE_STATE DATA_LSB FLOW_CONTROL _08 '
        'HIGH_CURRENTDRIVE _20 _40 SUSPEND_DBUS7')
    """Configuration bits stored @ 0x01."""

    VAR_STRINGS = ('manufacturer', 'product', 'serial')
    """EEPROM strings with variable length."""
    def __init__(self):
        self.log = getLogger('pyftdi.eeprom')
        self._ftdi = Ftdi()
        self._eeprom = bytearray()
        self._dev_ver = 0
        self._valid = False
        self._config = OrderedDict()
        self._dirty = set()
        self._modified = False

    def __getattr__(self, name):
        if name in self._config:
            return self._config[name]
        raise AttributeError('No such attribute: %s' % name)

    def open(self,
             device: Union[str, UsbDevice],
             ignore: bool = False) -> None:
        """Open a new connection to the FTDI USB device.

           :param device: the device URL or a USB device instance.
           :param ignore: whether to ignore existing content
        """
        if self._ftdi.is_connected:
            raise FtdiError('Already open')
        if isinstance(device, str):
            self._ftdi.open_from_url(device)
        else:
            self._ftdi.open_from_device(device)
        if not ignore:
            self._eeprom = self._read_eeprom()
            if self._valid:
                self._decode_eeprom()

    def close(self) -> None:
        """Close the current connection to the FTDI USB device,
        """
        if self._ftdi.is_connected:
            self._ftdi.close()
            self._eeprom = bytearray()
            self._dev_ver = 0
            self._config.clear()

    def connect(self, ftdi: Ftdi, ignore: bool = False) -> None:
        """Connect a FTDI EEPROM to an existing Ftdi instance.

           :param ftdi: the Ftdi instance to use
           :param ignore: whether to ignore existing content
        """
        self._ftdi = ftdi
        self._eeprom = bytearray()
        self._dev_ver = 0
        self._valid = False
        self._config = OrderedDict()
        self._dirty = set()
        if not ignore:
            self._eeprom = self._read_eeprom()
            if self._valid:
                self._decode_eeprom()
            self._decode_eeprom()

    @property
    def device_version(self) -> int:
        """Report the version of the FTDI device.

           :return: the release
        """
        if not self._dev_ver:
            if not self._ftdi.is_connected:
                raise FtdiError('Not connected')
            self._dev_ver = self._ftdi.device_version
        return self._dev_ver

    @property
    def size(self) -> int:
        """Report the EEPROM size.

           The physical EEPROM size may be greater.

           :return: the size in bytes
        """
        try:
            eeprom_size = self._PROPERTIES[self.device_version].size
        except (AttributeError, KeyError):
            raise FtdiError('No EEPROM')
        return eeprom_size

    @property
    def data(self) -> bytes:
        """Returns the content of the EEPROM.

           :return: the content as bytes.
        """
        self._sync_eeprom()
        return bytes(self._eeprom)

    @property
    def properties(self) -> Set[str]:
        """Returns the supported properties for the current device.

           :return: the supported properies.
        """
        props = set(self._config.keys())
        props -= set(self.VAR_STRINGS)
        return props

    @property
    def is_empty(self) -> bool:
        """Reports whether the EEPROM has been erased, or no EEPROM is
           connected to the FTDI EEPROM port.

           :return: True if no content is detected
        """
        if len(self._eeprom) != self._PROPERTIES[self.device_version].size:
            return False
        for byte in self._eeprom:
            if byte != 0xFF:
                return False
        return True

    @property
    def cbus_pins(self) -> List[int]:
        """Return the list of CBUS pins configured as GPIO, if any

           :return: list of CBUS pins
        """
        pins = [
            pin for pin in range(0, 10)
            if self._config.get('cbus_func_%d' % pin, '') == 'GPIO'
        ]
        return pins

    @property
    def cbus_mask(self) -> int:
        """Return the bitmask of CBUS pins configured as GPIO.

           The bitmap contains four bits, ordered in natural order.

           :return: CBUS mask
        """
        if self.device_version == 0x900:  # FT232H
            cbus = [5, 6, 8, 9]
        else:
            cbus = list(range(4))
        mask = 0
        for bix, pin in enumerate(cbus):
            if self._config.get('cbus_func_%d' % pin, '') == 'GPIO':
                mask |= 1 << bix
        return mask

    def save_config(self, file: TextIO) -> None:
        """Save the EEPROM content as an INI stream.

           :param file: output stream
        """
        self._sync_eeprom()
        cfg = ConfigParser()
        cfg.add_section('values')
        for name, value in self._config.items():
            cfg.set('values', name, str(value))
        cfg.add_section('raw')
        length = 16
        for i in range(0, len(self._eeprom), length):
            chunk = self._eeprom[i:i + length]
            hexa = hexlify(chunk).decode()
            cfg.set('raw', '@%02x' % i, hexa)
        cfg.write(file)

    def load_config(self, file: TextIO, section: Optional[str] = None) -> None:
        """Load the EEPROM content from an INI stream.

           The ``section`` argument selects which section(s) to load:

           * ``raw`` only loads the raw data (hexabytes) from a previous dump
           * ``values`` only loads the values section, that is the human
             readable configuration.
           * ``all``, which is the default section selection, load the raw
             section, then overwrite part of it with any configuration value
             from the ``values`` section. This provides a handy way to use an
             existing dump from a valid EEPROM content, while customizing some
             parameters, such as the serial number.

           :param file: input stream
           :paran section: which section to load from the ini file
        """
        self._sync_eeprom()
        cfg = ConfigParser()
        cfg.read_file(file)
        loaded = False
        sect = 'raw'
        if section in (None, 'all', sect, ''):
            if not cfg.has_section(sect):
                raise FtdiEepromError("No '%s' section in INI file" % sect)
            options = cfg.options(sect)
            try:
                for opt in options:
                    if not opt.startswith('@'):
                        raise ValueError()
                    address = int(opt[1:], 16)
                    hexval = cfg.get(sect, opt).strip()
                    buf = unhexlify(hexval)
                    self._eeprom[address:address + len(buf)] = buf
            except IndexError:
                raise ValueError("Invalid address in '%s'' section" % sect)
            except ValueError:
                raise ValueError("Invalid line in '%s'' section" % sect)
            self._compute_crc(self._eeprom, True)
            if not self._valid:
                raise ValueError('Loaded RAW section is invalid (CRC mismatch')
            loaded = True
        sect = 'values'
        vmap = {
            'manufacturer': 'manufacturer_name',
            'product': 'product_name',
            'serial': 'serial_number'
        }
        if section in (None, 'all', sect, ''):
            if not cfg.has_section(sect):
                raise FtdiEepromError("No '%s' section in INI file" % sect)
            options = cfg.options(sect)
            for opt in options:
                value = cfg.get(sect, opt).strip()
                if opt in vmap:
                    func = getattr(self, 'set_%s' % vmap[opt])
                    func(value)
                else:
                    try:
                        self.set_property(opt, value)
                    except ValueError:
                        self.log.warning(
                            "Ignoring setting '%s': "
                            "not implemented", opt)
            loaded = True
        if not loaded:
            raise ValueError('Invalid section: %s' % section)
        self._sync_eeprom()

    def set_serial_number(self, serial: str) -> None:
        """Define a new serial number."""
        self._validate_string(serial)
        self._update_var_string('serial', serial)
        self.set_property('has_serial', True)

    def set_manufacturer_name(self, manufacturer: str) -> None:
        """Define a new manufacturer string."""
        self._validate_string(manufacturer)
        self._update_var_string('manufacturer', manufacturer)

    def set_product_name(self, product: str) -> None:
        """Define a new product name."""
        self._validate_string(product)
        self._update_var_string('product', product)

    def set_property(self,
                     name: str,
                     value: Union[str, int, bool],
                     out: Optional[TextIO] = None) -> None:
        """Change the value of a stored property.

           :see: :py:meth:`properties` for a list of valid property names.
                 Note that for now, only a small subset of properties can be
                 changed.
           :param name: the property to change
           :param value: the new value (supported values depend on property)
           :param out: optional output stream to report hints
        """
        mobj = match(r'cbus_func_(\d)', name)
        if mobj:
            if not isinstance(value, str):
                raise ValueError("'%s' should be specified as a string" % name)
            self._set_cbus_func(int(mobj.group(1)), value, out)
            self._dirty.add(name)
            return
        mobj = match(r'([abcd])bus_(drive|slow_slew|schmitt)', name)
        if mobj:
            self._set_bus_control(mobj.group(1), mobj.group(2), value, out)
            self._dirty.add(name)
            return
        hwords = {
            'vendor_id': 0x02,
            'product_id': 0x04,
            'type': 0x06,
            'usb_version': 0x0c
        }
        if name in hwords:
            val = to_int(value)
            if not 0 <= val <= 0xFFFF:
                raise ValueError('Invalid value for %s' % name)
            offset = hwords[name]
            self._eeprom[offset:offset + 2] = spack('<H', val)
            return
        confs = {
            'remote_wakeup': (0, 5),
            'self_powered': (0, 6),
            'in_isochronous': (2, 0),
            'out_isochronous': (2, 1),
            'suspend_pull_down': (2, 2),
            'has_serial': (2, 3),
        }
        if name in confs:
            val = to_bool(value, permissive=False, allow_int=True)
            offset, bit = confs[name]
            mask = 1 << bit
            if val:
                self._eeprom[0x08 + offset] |= mask
            else:
                self._eeprom[0x0a + offset] &= ~mask
            return
        if name == 'power_max':
            val = to_int(value) >> 1
            self._eeprom[0x09] = val
            return
        if name.startswith('invert_'):
            if not self.device_version in (0x600, 0x1000):
                raise ValueError('UART control line inversion not available '
                                 'with this device')
            self._set_invert(name[len('invert_'):], value, out)
            self._dirty.add(name)
            return
        if name in self.properties:
            raise NotImplementedError("Change to '%s' is not yet supported" %
                                      name)
        raise ValueError("Unknown property '%s'" % name)

    def erase(self) -> None:
        """Erase the whole EEPROM."""
        self._eeprom = bytearray([0xFF] * self.size)
        self._config.clear()
        self._dirty.add('eeprom')

    def initialize(self) -> None:
        """Initialize the EEPROM with some default sensible values.
        """
        dev_ver = self.device_version
        dev_name = Ftdi.DEVICE_NAMES[dev_ver]
        vid = Ftdi.FTDI_VENDOR
        pid = Ftdi.PRODUCT_IDS[vid][dev_name]
        self.set_manufacturer_name('FTDI')
        self.set_product_name(dev_name.upper())
        sernum = ''.join([chr(randint(ord('A'), ord('Z'))) for _ in range(5)])
        self.set_serial_number('FT%d%s' % (randint(0, 9), sernum))
        self.set_property('vendor_id', vid)
        self.set_property('product_id', pid)
        self.set_property('type', dev_ver)
        self.set_property('usb_version', 0x200)
        self.set_property('power_max', 150)
        self._sync_eeprom()

    def sync(self) -> None:
        """Force re-evaluation of configuration after some changes.

           This API is not useful for regular usage, but might help for testing
           when the EEPROM does not go through a full save/load cycle
        """
        self._sync_eeprom()

    def dump_config(self, file: Optional[BinaryIO] = None) -> None:
        """Dump the configuration to a file.

           :param file: the output file, default to stdout
        """
        if self._dirty:
            self._decode_eeprom()
        for name, value in self._config.items():
            print('%s: %s' % (name, value), file=file or sys.stdout)

    def commit(self, dry_run: bool = True) -> bool:
        """Commit any changes to the EEPROM.

           :param dry_run: log what should be written, do not actually
                           change the EEPROM content

           :return: True if some changes have been committed to the EEPROM
        """
        self._sync_eeprom()
        if not self._modified:
            self.log.warning('No change to commit, EEPROM not modified')
            return False
        self._ftdi.overwrite_eeprom(self._eeprom, dry_run=dry_run)
        if not dry_run:
            eeprom = self._read_eeprom()
            if eeprom != self._eeprom:
                pos = 0
                for pos, (old, new) in enumerate(zip(self._eeprom, eeprom)):
                    if old != new:
                        break
                pos &= ~0x1
                raise FtdiEepromError('Write to EEPROM failed @ 0x%02x' % pos)
            self._modified = False
        return dry_run

    def reset_device(self):
        """Execute a USB device reset."""
        self._ftdi.reset(usb_reset=True)

    @classmethod
    def _validate_string(cls, string):
        for invchr in ':/':
            # do not accept characters which are interpreted as URL seperators
            if invchr in string:
                raise ValueError("Invalid character '%s' in string" % invchr)

    def _update_var_string(self, name: str, value: str) -> None:
        if name not in self.VAR_STRINGS:
            raise ValueError('%s is not a variable string' % name)
        try:
            if value == self._config[name]:
                return
        except KeyError:
            # not yet defined
            pass
        self._config[name] = value
        self._dirty.add(name)

    def _generate_var_strings(self, fill=True) -> None:
        stream = bytearray()
        dynpos = self._PROPERTIES[self.device_version].dynoff
        data_pos = dynpos
        tbl_pos = 0x0e
        for name in self.VAR_STRINGS:
            try:
                ustr = self._config[name].encode('utf-16le')
            except KeyError:
                ustr = ''
            length = len(ustr) + 2
            stream.append(length)
            stream.append(0x03)  # string descriptor
            stream.extend(ustr)
            self._eeprom[tbl_pos] = data_pos
            tbl_pos += 1
            self._eeprom[tbl_pos] = length
            tbl_pos += 1
            data_pos += length
        self._eeprom[dynpos:dynpos + len(stream)] = stream
        crc_size = scalc('<H')
        if fill:
            mtp = self._ftdi.device_version == 0x1000
            crc_pos = 0x100 if mtp else len(self._eeprom)
            crc_pos -= crc_size
            rem = len(self._eeprom) - (dynpos + len(stream)) - crc_size
            self._eeprom[dynpos + len(stream):crc_pos] = bytes(rem)

    def _sync_eeprom(self):
        if not self._dirty:
            self.log.debug('No change detected for EEPROM content')
            return
        if any([x in self._dirty for x in self.VAR_STRINGS]):
            self._generate_var_strings()
            for varstr in self.VAR_STRINGS:
                self._dirty.discard(varstr)
        self._update_crc()
        self._decode_eeprom()
        self._dirty.clear()
        self._modified = True
        self.log.debug('EEPROM content regenerated (not yet committed)')

    def _compute_crc(self, eeprom: Union[bytes, bytearray], check=False):
        mtp = self._ftdi.device_version == 0x1000
        crc_pos = 0x100 if mtp else len(eeprom)
        crc_size = scalc('<H')
        if not check:
            # check mode: add CRC itself, so that result should be zero
            crc_pos -= crc_size
        crc = self._ftdi.calc_eeprom_checksum(eeprom[:crc_pos])
        if check:
            self._valid = not bool(crc)
            if not self._valid:
                self.log.debug('CRC is now 0x%04x', crc)
            else:
                self.log.debug('CRC OK')
        return crc, crc_pos, crc_size

    def _update_crc(self):
        crc, crc_pos, crc_size = self._compute_crc(self._eeprom, False)
        self._eeprom[crc_pos:crc_pos + crc_size] = spack('<H', crc)

    def _read_eeprom(self) -> bytes:
        buf = self._ftdi.read_eeprom(0, eeprom_size=self.size)
        eeprom = bytearray(buf)
        crc = self._compute_crc(eeprom, True)[0]
        if crc:
            if self.is_empty:
                self.log.info('No EEPROM or EEPROM erased')
            else:
                self.log.error('Invalid CRC or EEPROM content')
        return eeprom

    def _decode_eeprom(self):
        cfg = self._config
        cfg.clear()
        cfg['vendor_id'] = Hex4Int(sunpack('<H', self._eeprom[0x02:0x04])[0])
        cfg['product_id'] = Hex4Int(sunpack('<H', self._eeprom[0x04:0x06])[0])
        cfg['type'] = Hex4Int(sunpack('<H', self._eeprom[0x06:0x08])[0])
        power_supply, power_max, conf = sunpack('<3B', self._eeprom[0x08:0x0b])
        cfg['self_powered'] = bool(power_supply & (1 << 6))
        cfg['remote_wakeup'] = bool(power_supply & (1 << 5))
        cfg['power_max'] = power_max << 1
        cfg['has_serial'] = bool(conf & (1 << 3))
        cfg['suspend_pull_down'] = bool(conf & (1 << 2))
        cfg['out_isochronous'] = bool(conf & (1 << 1))
        cfg['in_isochronous'] = bool(conf & (1 << 0))
        cfg['usb_version'] = Hex4Int(sunpack('<H', self._eeprom[0x0c:0x0e])[0])
        cfg['manufacturer'] = self._decode_string(0x0e)
        cfg['product'] = self._decode_string(0x10)
        cfg['serial'] = self._decode_string(0x12)
        name = None
        try:
            name = Ftdi.DEVICE_NAMES[cfg['type']].replace('-', '')
            if name.startswith('ft'):
                name = name[2:]
            func = getattr(self, '_decode_%s' % name)
        except (KeyError, AttributeError):
            self.log.warning('No EEPROM decoder for device %s', name or '?')
        else:
            func()

    def _decode_string(self, offset):
        str_offset, str_size = sunpack('<BB', self._eeprom[offset:offset + 2])
        if str_size:
            str_offset &= self.size - 1
            str_size -= scalc('<H')
            str_offset += scalc('<H')
            manufacturer = self._eeprom[str_offset:str_offset + str_size]
            return manufacturer.decode('utf16', errors='ignore')
        return ''

    def _set_cbus_func(self, cpin: int, value: str,
                       out: Optional[TextIO]) -> None:
        cmap = {
            0x600: (self.CBUS, 5, 0x14, 4),  # FT232R
            0x900: (self.CBUSH, 10, 0x18, 4),  # FT232H
            0x1000: (self.CBUSX, 4, 0x1A, 8)
        }  # FT230X/FT231X/FT234X
        try:
            cbus, count, offset, width = cmap[self.device_version]
        except KeyError:
            raise ValueError('This property is not supported on this device')
        pin_filter = getattr(self,
                             '_filter_cbus_func_x%x' % self.device_version,
                             None)
        if value == '?' and out:
            items = {item.name for item in cbus}
            if pin_filter:
                items = {val for val in items if pin_filter(cpin, val)}
            print(', '.join(sorted(items)) if items else '(none)', file=out)
            return
        if not 0 <= cpin < count:
            raise ValueError("Unsupported CBUS pin '%d'" % cpin)
        try:
            code = cbus[value.upper()].value
        except KeyError:
            raise ValueError("CBUS pin %d does not have function '%s'" %
                             (cpin, value))
        if pin_filter and not pin_filter(cpin, value.upper()):
            raise ValueError("Unsupported CBUS function '%s' for pin '%d'" %
                             (value, cpin))
        addr = offset + (cpin * width) // 8
        if width == 4:
            bitoff = 4 if cpin & 0x1 else 0
            mask = 0x0F << bitoff
        else:
            bitoff = 0
            mask = 0xFF
        old = self._eeprom[addr]
        self._eeprom[addr] &= ~mask
        self._eeprom[addr] |= code << bitoff
        self.log.debug('Cpin %d, addr 0x%02x, value 0x%02x->0x%02x', cpin,
                       addr, old, self._eeprom[addr])

    @classmethod
    def _filter_cbus_func_x900(cls, cpin: int, value: str):
        if cpin == 7:
            # nothing can be assigned to ACBUS7
            return False
        if value in 'TRISTATE TXLED RXLED TXRXLED PWREN SLEEP DRIVE0'.split():
            # any pin can be assigned these functions
            return True
        if cpin in (5, 6, 8, 9):
            # any function can be assigned to ACBUS5, ACBUS6, ACBUS8, ACBUS9
            return True
        if cpin == 0:
            return value != 'GPIO'
        return False

    @classmethod
    def _filter_cbus_func_x600(cls, cpin: int, value: str):
        if value == 'BB_WR':
            # this signal is only available on CBUS0, CBUS1
            return cpin < 2
        return True

    def _set_bus_control(self, bus: str, control: str, value: Union[str, int,
                                                                    bool],
                         out: Optional[TextIO]) -> None:
        if self.device_version == 0x1000:
            self._set_bus_control_230x(bus, control, value, out)
            return
        # for now, only support FT-X devices
        raise ValueError('Bus control not implemented for this device')

    def _set_bus_control_230x(self, bus: str, control: str,
                              value: Union[str, int, bool],
                              out: Optional[TextIO]) -> None:
        if bus not in 'cd':
            raise ValueError('Invalid bus: %s' % bus)
        try:
            if control == 'drive':
                candidates = (4, 8, 12, 16)
                if value == '?' and out:
                    print(', '.join([str(v) for v in candidates]), file=out)
                    return
                value = int(value)
                if value not in candidates:
                    raise ValueError('Invalid drive current: %d mA' % value)
                value //= 4
                value -= 1
            elif control in ('slow_slew', 'schmitt'):
                if value == '?' and out:
                    print('off, on', file=out)
                    return
                value = int(to_bool(value))
            else:
                raise ValueError('Unsupported control: %s' % control)
        except (ValueError, TypeError):
            raise ValueError('Invalid %s value: %s' % (control, value))
        config = self._eeprom[0x0c]
        if bus == 'd':
            conf = config & 0x0F
            config &= 0xF0
            cshift = 0
        else:
            conf = config >> 4
            config &= 0x0F
            cshift = 4
        if control == 'drive':
            conf &= 0b1100
            conf |= value
        elif control == 'slow_slew':
            conf &= 0b1011
            conf |= value << 2
        elif control == 'schmitt':
            conf &= 0b0111
            conf |= value << 3
        else:
            raise RuntimeError('Internal error')
        config |= conf << cshift
        self._eeprom[0x0c] = config

    def _set_invert(self, name, value, out):
        if value == '?' and out:
            print('off, on', file=out)
            return
        if name.upper() not in self.UART_BITS.__members__:
            raise ValueError('Unknown property: %s' % name)
        value = to_bool(value, permissive=False)
        code = getattr(self.UART_BITS, name.upper())
        invert = self._eeprom[0x0B]
        if value:
            invert |= code
        else:
            invert &= ~code
        self._eeprom[0x0B] = invert

    def _decode_x(self):
        # FT-X series
        cfg = self._config
        misc, = sunpack('<H', self._eeprom[0x00:0x02])
        cfg['channel_a_driver'] = 'VCP' if misc & (1 << 7) else 'D2XX'
        for bit in self.UART_BITS:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.UART_BITS(bit).name] = bool(value & bit)
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        value = self._eeprom[0x0c]
        for grp in range(2):
            conf = value & 0xF
            bus = 'c' if grp else 'd'
            cfg['%sbus_drive' % bus] = 4 * (1 + (conf & max_drive))
            cfg['%sbus_schmitt' % bus] = bool(conf & self.DRIVE.SCHMITT)
            cfg['%sbus_slow_slew' % bus] = bool(conf & self.DRIVE.SLOW_SLEW)
            value >>= 4
        for bix in range(4):
            value = self._eeprom[0x1A + bix]
            try:
                cfg['cbus_func_%d' % bix] = self.CBUSX(value).name
            except ValueError:
                pass
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232h(self):
        cfg = self._config
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = cfg0 & 0x0F
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 4)) else 'D2XX'
        cfg['clock_polarity'] = 'high' if (cfg1 & self.CFG1.CLK_IDLE_STATE) \
                                else 'low'
        cfg['lsb_data'] = bool(cfg1 & self.CFG1.DATA_LSB)
        cfg['flow_control'] = 'on' if (cfg1 & self.CFG1.FLOW_CONTROL) \
                              else 'off'
        cfg['powersave'] = bool(cfg1 & self.DRIVE.PWRSAVE_DIS)
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        for grp in range(2):
            conf = self._eeprom[0x0c + grp]
            cfg['group_%d_drive' % grp] = bool((conf & max_drive) == max_drive)
            cfg['group_%d_schmitt' % grp] = conf & self.DRIVE.SCHMITT
            cfg['group_%d_slew' % grp] = conf & self.DRIVE.SLOW_SLEW
        for bix in range(5):
            value = self._eeprom[0x18 + bix]
            low, high = value & 0x0F, value >> 4
            try:
                cfg['cbus_func_%d' % ((2 * bix) + 0)] = self.CBUSH(low).name
            except ValueError:
                pass
            try:
                cfg['cbus_func_%d' % ((2 * bix) + 1)] = self.CBUSH(high).name
            except ValueError:
                pass
        cfg['chip'] = Hex2Int(self._eeprom[0x1E])

    def _decode_232r(self):
        cfg = self._config
        cfg0 = self._eeprom[0x00]
        cfg['channel_a_driver'] = 'VCP' if (~cfg0 & (1 << 3)) else ''
        cfg['high_current'] = bool(~cfg0 & (1 << 2))
        cfg['external_oscillator'] = cfg0 & 0x02
        for bit in self.UART_BITS:
            value = self._eeprom[0x0B]
            cfg['invert_%s' % self.UART_BITS(bit).name] = bool(value & bit)
        bix = 0
        while True:
            value = self._eeprom[0x14 + bix]
            low, high = value & 0x0F, value >> 4
            try:
                cfg['cbus_func_%d' % ((2 * bix) + 0)] = self.CBUS(low).name
            except ValueError:
                pass
            if bix == 2:
                break
            try:
                cfg['cbus_func_%d' % ((2 * bix) + 1)] = self.CBUS(high).name
            except ValueError:
                pass
            bix += 1

    def _decode_2232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_type'] = self.CHANNEL(cfg0 & 0x7).name or 'UART'
        cfg['channel_b_type'] = self.CHANNEL(cfg1 & 0x7).name or 'UART'
        cfg['suspend_dbus7'] = cfg1 & self.CFG1.SUSPEND_DBUS7

    def _decode_4232h(self):
        cfg = self._config
        self._decode_x232h(cfg)
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_c_driver'] = 'VCP' if ((cfg0 >> 4) & (1 << 3)) else 'D2XX'
        cfg['channel_d_driver'] = 'VCP' if ((cfg1 >> 4) & (1 << 3)) else 'D2XX'
        conf = self._eeprom[0x0B]
        rs485 = self.CHANNEL.RS485
        for chix in range(4):
            cfg['channel_%x_rs485' % (0xa + chix)] = bool(conf
                                                          & (rs485 << chix))

    def _decode_x232h(self, cfg):
        # common code for2232h and 4232h
        cfg0, cfg1 = self._eeprom[0x00], self._eeprom[0x01]
        cfg['channel_a_driver'] = 'VCP' if (cfg0 & (1 << 3)) else 'D2XX'
        cfg['channel_b_driver'] = 'VCP' if (cfg1 & (1 << 3)) else 'D2XX'
        max_drive = self.DRIVE.LOW | self.DRIVE.HIGH
        for bix in range(4):
            if not bix & 1:
                val = self._eeprom[0x0c + bix // 2]
            else:
                val >>= 4
            cfg['group_%d_drive' % bix] = bool(val & max_drive)
            cfg['group_%d_schmitt' % bix] = bool(val & self.DRIVE.SCHMITT)
            cfg['group_%d_slew' % bix] = bool(val & self.DRIVE.SLOW_SLEW)
        cfg['chip'] = Hex2Int(self._eeprom[0x18])
Example #23
0
    from _ssl import RAND_egd
except ImportError:
    # LibreSSL does not provide RAND_egd
    pass

from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_SSLv2, HAS_SSLv3, HAS_TLSv1, HAS_TLSv1_1, HAS_TLSv1_2, HAS_TLSv1_3
from _ssl import _DEFAULT_CIPHERS, _OPENSSL_API_VERSION

_IntEnum._convert(
    "_SSLMethod",
    __name__,
    lambda name: name.startswith("PROTOCOL_") and name != "PROTOCOL_SSLv23",
    source=_ssl)

_IntFlag._convert("Options",
                  __name__,
                  lambda name: name.startswith("OP_"),
                  source=_ssl)

_IntEnum._convert("AlertDescription",
                  __name__,
                  lambda name: name.startswith("ALERT_DESCRIPTION_"),
                  source=_ssl)

_IntEnum._convert("SSLErrorNumber",
                  __name__,
                  lambda name: name.startswith("SSL_ERROR_"),
                  source=_ssl)

_IntFlag._convert("VerifyFlags",
                  __name__,
                  lambda name: name.startswith("VERIFY_"),
Example #24
0
    from _ssl import RAND_egd
except ImportError:
    # LibreSSL does not provide RAND_egd
    pass

from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN, HAS_TLSv1_3
from _ssl import _OPENSSL_API_VERSION

_IntEnum._convert(
    '_SSLMethod',
    __name__,
    lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
    source=_ssl)

_IntFlag._convert('Options',
                  __name__,
                  lambda name: name.startswith('OP_'),
                  source=_ssl)

_IntEnum._convert('AlertDescription',
                  __name__,
                  lambda name: name.startswith('ALERT_DESCRIPTION_'),
                  source=_ssl)

_IntEnum._convert('SSLErrorNumber',
                  __name__,
                  lambda name: name.startswith('SSL_ERROR_'),
                  source=_ssl)

_IntFlag._convert('VerifyFlags',
                  __name__,
                  lambda name: name.startswith('VERIFY_'),
Example #25
0
from math import pi, pow
from datetime import datetime, timedelta, timezone
from doop.constants import Earth
from collections import namedtuple

from enum import IntFlag

ID = namedtuple("ID", "launch_year launch_number piece")
Object = namedtuple("Object", "name number classification")

EphemerisType = IntFlag("EphemerisType", "SGP SGP4 SDP4 SGP8 SDP8")

TLE = namedtuple(
    "TLE", 'object '
    'id '
    'coe '
    'ballistic_coeffecient '
    'bstar '
    'line1 line2')

OE = namedtuple("OE", "a e i raan w v")


def fix_classification(x):
    if x == "U":
        return "Unclassified"
    elif x == "C":
        return "Classified"
    elif x == "S":
        return "Secret"
    raise Exception(f"Invalid classification: {x}")
Example #26
0
# Copyright (c) 2014 Kevin Walchko
# see LICENSE for full details
##############################################
# -*- coding: utf-8 -*
from colorama import Fore
import io
from threading import Thread  #, Lock
import time
from slurm.rate import Rate
import numpy as np
import cv2
from enum import IntFlag
import attr

#                                   1   2   3   4
ColorSpace = IntFlag("ColorSpace", "bgr rgb hsv gray")


@attr.s(slots=True)
class ThreadedCamera:
    """
    https://www.raspberrypi.org/documentation/hardware/camera/
    Raspberry Pi v2:
        resolution: 3280 x 2464 pixels
        sensor area: 3.68 mm x 2.76 mm
        pixel size: 1.12 um x 1.12 um
        video modes:1080p30, 720p60 and 640x480p60/90
        optical size: 1/4"
        driver: V4L2 driver

    c = ThreadedCamera()
Example #27
0
File: ssl.py Project: 3lnc/cpython
except ImportError:
    # LibreSSL does not provide RAND_egd
    pass


from _ssl import HAS_SNI, HAS_ECDH, HAS_NPN, HAS_ALPN
from _ssl import _OPENSSL_API_VERSION


_IntEnum._convert(
    '_SSLMethod', __name__,
    lambda name: name.startswith('PROTOCOL_') and name != 'PROTOCOL_SSLv23',
    source=_ssl)

_IntFlag._convert(
    'Options', __name__,
    lambda name: name.startswith('OP_'),
    source=_ssl)

_IntEnum._convert(
    'AlertDescription', __name__,
    lambda name: name.startswith('ALERT_DESCRIPTION_'),
    source=_ssl)

_IntEnum._convert(
    'SSLErrorNumber', __name__,
    lambda name: name.startswith('SSL_ERROR_'),
    source=_ssl)

_IntFlag._convert(
    'VerifyFlags', __name__,
    lambda name: name.startswith('VERIFY_'),
Example #28
0
def create_swapchain():
    global swapchain_image_format, swapchain

    # Swapchain Setup
    caps = hvk.physical_device_surface_capabilities(api, physical_device,
                                                    surface)
    formats = hvk.physical_device_surface_formats(api, physical_device,
                                                  surface)
    present_modes = hvk.physical_device_surface_present_modes(
        api, physical_device, surface)

    if not hvk.get_physical_device_surface_support(
            api, physical_device, surface, render_queue.family.index):
        raise RuntimeError(
            "Main rendering queue cannot present images to the surface")

    # Swapchain Format
    format_values = tuple(vkf.format for vkf in formats)
    required_formats = [vk.FORMAT_B8G8R8A8_SRGB, vk.FORMAT_B8G8R8A8_UNORM]
    for i, required_format in enumerate(required_formats):
        if required_format in format_values:
            required_formats[i] = format_values.index(required_format)
        else:
            required_formats[i] = None

    selected_format = next(
        (formats[i] for i in required_formats if i is not None), None)
    if selected_format is None:
        raise RuntimeError("Required swapchain image format not supported")

    # Swapchain Extent
    extent = caps.current_extent
    if extent.width == -1 or extent.height == -1:
        width, height = window.dimensions()
        extent.width = width
        extent.height = height

    # Min image count
    min_image_count = 2
    if caps.max_image_count != 0 and caps.max_image_count < min_image_count:
        raise RuntimeError("Minimum image count not met")
    elif caps.min_image_count > min_image_count:
        min_image_count = caps.min_image_count

    # Present mode
    present_mode = vk.PRESENT_MODE_FIFO_KHR
    if vk.PRESENT_MODE_MAILBOX_KHR in present_modes:
        present_mode = vk.PRESENT_MODE_MAILBOX_KHR
    elif vk.PRESENT_MODE_IMMEDIATE_KHR in present_modes:
        present_mode = vk.PRESENT_MODE_IMMEDIATE_KHR

    # Default image transformation
    transform = caps.current_transform
    if IntFlag(vk.SURFACE_TRANSFORM_IDENTITY_BIT_KHR) in IntFlag(
            caps.supported_transforms):
        transform = vk.SURFACE_TRANSFORM_IDENTITY_BIT_KHR

    # Swapchain creation
    swapchain_image_format = selected_format.format
    swapchain = hvk.create_swapchain(
        api, device,
        hvk.swapchain_create_info(
            surface=surface,
            image_format=swapchain_image_format,
            image_color_space=selected_format.color_space,
            image_extent=extent,
            min_image_count=min_image_count,
            present_mode=present_mode,
            pre_transform=transform,
            old_swapchain=0))
Example #29
0
from functools import partialmethod
from itertools import accumulate
from opcode import (
    EXTENDED_ARG,
    HAVE_ARGUMENT,
    cmp_op,
    hascompare,
    hasconst,
    hasfree,
    haslocal,
    hasname,
    opname,
)
from types import CodeType

CompilerFlags = IntFlag("CompilerFlags",
                        " ".join(COMPILER_FLAG_NAMES.values()))
MakeFunctionFlags = IntFlag(
    "MakeFunctionFlags",
    " ".join(flag.upper() for flag in MAKE_FUNCTION_FLAGS))


class CodeBuilderBase:
    def __init__(self):
        self.consts = {None: 0}
        self.names = {}
        self.varnames = {}
        self.cellvars = {}
        self.freevars = {}

    def ascode(self, func_name: str, argcount: int) -> CodeType:
        code = bytes(self)
Example #30
0
# Note that _socket only knows about the integer values. The public interface
# in this module understands the enums and translates them back from integers
# where needed (e.g. .family property of a socket object).

IntEnum._convert_(
        'AddressFamily',
        __name__,
        lambda C: C.isupper() and C.startswith('AF_'))

IntEnum._convert_(
        'SocketKind',
        __name__,
        lambda C: C.isupper() and C.startswith('SOCK_'))

IntFlag._convert_(
        'MsgFlag',
        __name__,
        lambda C: C.isupper() and C.startswith('MSG_'))

IntFlag._convert_(
        'AddressInfo',
        __name__,
        lambda C: C.isupper() and C.startswith('AI_'))

_LOCALHOST    = '127.0.0.1'
_LOCALHOST_V6 = '::1'


def _intenum_converter(value, enum_klass):
    """Convert a numeric family value to an IntEnum member.

    If it's not a known member, return the numeric value itself.
Example #31
0
    def _setup_device(self):
        api, instance = self.api, self.instance
        conf = self.configuration
        queues_conf = conf.get("QUEUES", DEFAULT_ENGINE_CONFIGURATION["QUEUES"])

        # Device selection
        failure_reasons, all_good = [], False
        physical_devices = hvk.list_physical_devices(api, instance)
        
        for index, physical_device in enumerate(physical_devices):
            
            # Features
            supported_features = hvk.physical_device_features(api, physical_device)
            if not "texture_compression_BC" in supported_features:
                failure_reasons.append(f"BC compressed textures are not supported on your machine on device #{index}")
                continue

            # Queues
            queue_families = hvk.list_queue_families(api, physical_device)
            queue_create_infos = []
            mapped_queue_configurations = {}
            render_queue_data = None
            bad_queues = False

            for qconf in queues_conf:
                queue_family = None

                # Find a matching queue family
                for qf in queue_families:
                    if qconf.type in IntFlag(qf.properties.queue_flags):
                        queue_family = qf
                
                # Go to the next device if a required queue configuration could not be found
                if qconf.required and queue_family is None:
                    bad_queues = True
                    failure_reasons.append(f"No queue family matches the required configuration {qconf} on device #{index}")
                    break

                # Update the queue create info array
                new_info = {"queue_family_index": queue_family.index, "queue_count": 0}
                queue_create_info = next((qc for qc in queue_create_infos if qc["queue_family_index"] == queue_family.index), new_info)
                queue_create_infos.append(queue_create_info)
                queue_local_index = queue_create_info["queue_count"]
                queue_create_info["queue_count"] += 1
            
                # Save the index of the required graphics queue that will be used by the renderer
                if render_queue_data is None and QueueType.Graphics in qconf.type:
                    render_queue_data = (queue_family, queue_local_index)

                # Associate the queue configuration with the family and the local index for queue handle fetching
                mapped_queue_configurations[qconf] = (queue_family, queue_local_index)

            if bad_queues:
                continue

            all_good = True
            break

        if not all_good:
            raise RuntimeError(failure_reasons)

        if render_queue_data is None:
            raise RuntimeError("No graphics queue was specified in the engine queues configuration. Protip: use \"QueueConf.Default\" ")

        # Device creation
        queue_create_infos = [hvk.queue_create_info(**args) for args in queue_create_infos]
        extensions = ("VK_KHR_swapchain",)
        features = vk.PhysicalDeviceFeatures(texture_compression_BC = 1)
        device = hvk.create_device(api, physical_device, extensions, queue_create_infos, features)

        # Fetching queues
        # First, fetch the render queue
        render_queue_family, render_family_local_index = render_queue_data
        render_queue_handle = hvk.get_queue(api, device, render_queue_family.index, render_family_local_index)
        render_queue = Queue(render_queue_handle, render_queue_family)

        # Second, fetch all the queues (yes, the render queue is fetched twice)
        queues = {}
        for queue_conf, queue_data in mapped_queue_configurations.items():
            queue_family, local_index = queue_data
            queue_handle = hvk.get_queue(api, device, queue_family.index, local_index)
            queues[queue_conf.name] = Queue(queue_handle, queue_family)

        self.physical_device = physical_device
        self.device = device
        self.render_queue = render_queue
        self.queues = queues
Example #32
0
from enum import IntFlag
from random import choice, random
from time import sleep


def chance(percent):
    return random() < percent


def rand_char():
    return choice('█ ')


WALL, AIR, FLOOR, RANDOM = IntFlag('TileType', 'WALL AIR FLOOR RANDOM')

NEXT_TILETYPE = {
    WALL: lambda: WALL if chance(.8) else AIR,
    AIR: lambda: AIR if chance(.4) else RANDOM,
    FLOOR: lambda: RANDOM,
    RANDOM: lambda: choice((WALL, AIR, FLOOR))
}

TILETYPE_TO_CHARACTER = {
    WALL: lambda: '█',
    AIR: lambda: ' ',
    FLOOR: lambda: '_',
    RANDOM: lambda: rand_char(),
}


def run(row, *, delay=.5):
Example #33
0
#!/usr/bin/env python3

import threading
import time
from mbeacon import BeaconServer, BeaconFinder
# from collections import namedtuple
from enum import Enum, IntFlag

# Pub_t = namedtuple('Pub_t', 'key topic pid funcname')
# Sub_t = namedtuple('Sub_t', 'key topic pid funcname')
# Perf_t = namedtuple('Perf_t', 'key nummsg msgrate datarate funcname')
# Connect_t = namedtuple('Connect_t', 'topic ip')

MsgsIPC = Enum('MsgsIPC', 'Pub Sub Resp Perf')
TTL = IntFlag('TTL', {'host': 0, 'subnet': 1, 'site': 31})


class IPC:
    def __init__(self, key, kind, topic, pid, funcname):
        self.msg = (
            key,
            kind,
            topic,
            pid,
            funcname,
        )


class PubIPC(IPC):
    def __init__(self, key, topic, pid, funcname):
        IPC.__init__(