aboutsummaryrefslogtreecommitdiff
path: root/usb-control/cp210x_controller.py
blob: 47a79e6fd15b0ff8ea9aebae808df8decde935a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/usr/bin/env python3

"""Low-level library to control the CP210x.
"""

__copyright__ = 'Copyright (C) 2019 Theobroma Systems Design und Consulting GmbH'
__license__ = 'MIT'

import usb.core
import usb.util

VENDOR_ID = 0x10c4
PRODUCT_ID = 0xea60

REQTYPE_HOST_TO_DEVICE = 0x40
REQTYPE_DEVICE_TO_HOST = 0xc0

CP210X_VENDOR_SPECIFIC = 0xFF

CP210X_WRITE_LATCH = 0x37E1
CP210X_READ_LATCH = 0x00C2
CP210X_GET_MDMSTS = 0x8


def set_gpio(dev, gpio, value):
    # the latch register has 16 bit. the upper 8 bits are the gpio value,
    # the lower 8 bit are the write mask.
    val = (value << (8 + gpio)) | (1 << gpio)
    dev.ctrl_transfer(bmRequestType=REQTYPE_HOST_TO_DEVICE,
                      bRequest=CP210X_VENDOR_SPECIFIC,
                      wValue=CP210X_WRITE_LATCH,
                      wIndex=val)


def get_gpio(dev, gpio):
    # Read 1 byte from latch register
    data = dev.ctrl_transfer(bmRequestType=REQTYPE_DEVICE_TO_HOST,
                             bRequest=CP210X_VENDOR_SPECIFIC,
                             wValue=CP210X_READ_LATCH,
                             data_or_wLength=1)
    return not not (data[0] & (1 << gpio))


def get_modemstatus(dev):
    data = dev.ctrl_transfer(bmRequestType=REQTYPE_DEVICE_TO_HOST,
                             bRequest=CP210X_GET_MDMSTS,
                             wValue=0,
                             wIndex=0,
                             data_or_wLength=1)
    # Check CTS line
    return ((data[0] >> 4) & 1)


def find_board_list(product_string, serialnumber):
    """
    This function returns a list of found CP210x controllers.
    If product_string is not None it will be used for filtering.
    If serialnumber is not None it will be used for filtering.
    """
    try:
        kwargs = dict()
        kwargs['idVendor'] = VENDOR_ID
        kwargs['idProduct'] = PRODUCT_ID
        if product_string is not None:
            kwargs['product'] = product_string
        if serialnumber:
            kwargs['serial_number'] = serialnumber
        kwargs['find_all'] = True

        # Find the devices matching the specified requirements
        dev_it = usb.core.find(**kwargs)

        # Convert iterator to list and return
        devs = list(dev_it)
        return devs

    except ValueError as e:
        if 'langid' in e.message:
            raise usb.core.USBError(e.message + "\n" +
                                    "This may be a permission issue. See: \n" +
                                    "https://github.com/pyusb/pyusb/issues/139")