aboutsummaryrefslogtreecommitdiff
path: root/usb-control/cp210x_controller.py
blob: b4d9d153416249ea969c6c76dc67b4ec89a21066 (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
#!/usr/bin/env python

"""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 != 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, 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")