summaryrefslogtreecommitdiff
path: root/extra/tigertool/ecusb/stm32usb.py
blob: bfd5fbb1fbd1c5abd30605c0e4a42413907cf395 (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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Copyright 2017 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# Ignore indention messages, since legacy scripts use 2 spaces instead of 4.
# pylint: disable=bad-indentation,docstring-section-indent
# pylint: disable=docstring-trailing-quotes

"""Allows creation of an interface via stm32 usb."""

import usb


class SusbError(Exception):
  """Class for exceptions of Susb."""
  def __init__(self, msg, value=0):
    """SusbError constructor.

    Args:
      msg: string, message describing error in detail
      value: integer, value of error when non-zero status returned.  Default=0
    """
    super(SusbError, self).__init__(msg, value)
    self.msg = msg
    self.value = value


class Susb(object):
  """Provide stm32 USB functionality.

  Instance Variables:
    _read_ep: pyUSB read endpoint for this interface
    _write_ep: pyUSB write endpoint for this interface
  """
  READ_ENDPOINT = 0x81
  WRITE_ENDPOINT = 0x1
  TIMEOUT_MS = 100

  def __init__(self, vendor=0x18d1,
               product=0x5027, interface=1, serialname=None, logger=None):
    """Susb constructor.

    Discovers and connects to stm32 USB endpoints.

    Args:
      vendor: usb vendor id of stm32 device.
      product: usb product id of stm32 device.
      interface: interface number ( 1 - 4 ) of stm32 device to use.
      serialname: string of device serialname.
      logger: none

    Raises:
      SusbError: An error accessing Susb object
    """
    self._vendor = vendor
    self._product = product
    self._interface = interface
    self._serialname = serialname
    self._find_device()

  def _find_device(self):
    """Set up the usb endpoint"""
    # Find the stm32.
    dev_g = usb.core.find(idVendor=self._vendor, idProduct=self._product,
                             find_all=True)
    dev_list = list(dev_g)

    if not dev_list:
      raise SusbError('USB device not found')

    # Check if we have multiple stm32s and we've specified the serial.
    dev = None
    if self._serialname:
      for d in dev_list:
        dev_serial = usb.util.get_string(d, d.iSerialNumber)
        if dev_serial == self._serialname:
          dev = d
          break
      if dev is None:
        raise SusbError('USB device(%s) not found' % self._serialname)
    else:
      try:
        dev = dev_list[0]
      except StopIteration:
        raise SusbError('USB device %04x:%04x not found' % (
            self._vendor, self._product))

    # If we can't set configuration, it's already been set.
    try:
      dev.set_configuration()
    except usb.core.USBError:
      pass

    self._dev = dev

    # Get an endpoint instance.
    cfg = dev.get_active_configuration()
    intf = usb.util.find_descriptor(cfg, bInterfaceNumber=self._interface)
    self._intf = intf
    if not intf:
      raise SusbError('Interface %04x:%04x - 0x%x not found' % (
          self._vendor, self._product, self._interface))

    # Detach raiden.ko if it is loaded. CCD endpoints support either a kernel
    # module driver that produces a ttyUSB, or direct endpoint access, but
    # can't do both at the same time.
    if dev.is_kernel_driver_active(intf.bInterfaceNumber) is True:
      dev.detach_kernel_driver(intf.bInterfaceNumber)

    read_ep_number = intf.bInterfaceNumber + self.READ_ENDPOINT
    read_ep = usb.util.find_descriptor(intf, bEndpointAddress=read_ep_number)
    self._read_ep = read_ep

    write_ep_number = intf.bInterfaceNumber + self.WRITE_ENDPOINT
    write_ep = usb.util.find_descriptor(intf, bEndpointAddress=write_ep_number)
    self._write_ep = write_ep

  def close(self):
    usb.util.dispose_resources(self._dev)