libusbsio 2.1.13__tar.gz → 2.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. libusbsio-2.2.0/LICENSE.txt +2 -0
  2. libusbsio-2.2.0/MANIFEST.in +8 -0
  3. {libusbsio-2.1.13/libusbsio.egg-info → libusbsio-2.2.0}/PKG-INFO +16 -14
  4. {libusbsio-2.1.13 → libusbsio-2.2.0}/README.md +6 -2
  5. {libusbsio-2.1.13 → libusbsio-2.2.0}/examples/hid.py +1 -1
  6. {libusbsio-2.1.13 → libusbsio-2.2.0}/examples/i2c.py +1 -1
  7. {libusbsio-2.1.13 → libusbsio-2.2.0}/examples/ports.py +24 -5
  8. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/__init__.py +4 -4
  9. {libusbsio-2.1.13/license → libusbsio-2.2.0/libusbsio/bin}/BSD-3-clause.txt +1 -1
  10. libusbsio-2.2.0/libusbsio/bin/SBOM-libusbsio.spdx.json +95 -0
  11. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/Win32/libusbsio.dll +0 -0
  12. libusbsio-2.2.0/libusbsio/bin/linux_x86_64/libusbsio.so +0 -0
  13. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/osx_arm64/libusbsio.dylib +0 -0
  14. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/osx_x86_64/libusbsio.dylib +0 -0
  15. libusbsio-2.2.0/libusbsio/bin/x64/libusbsio.dll +0 -0
  16. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/libusbsio.py +169 -32
  17. {libusbsio-2.1.13 → libusbsio-2.2.0/libusbsio.egg-info}/PKG-INFO +16 -14
  18. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio.egg-info/SOURCES.txt +3 -2
  19. {libusbsio-2.1.13/libusbsio/bin → libusbsio-2.2.0/license}/BSD-3-clause.txt +1 -1
  20. libusbsio-2.2.0/license/SBOM-libusbsio.spdx.json +95 -0
  21. libusbsio-2.2.0/pyproject.toml +48 -0
  22. {libusbsio-2.1.13 → libusbsio-2.2.0}/test/test_00_lib.py +38 -21
  23. {libusbsio-2.1.13 → libusbsio-2.2.0}/test/test_10_spi.py +4 -9
  24. {libusbsio-2.1.13 → libusbsio-2.2.0}/test/test_20_i2c.py +5 -10
  25. libusbsio-2.2.0/test/test_base.py +129 -0
  26. libusbsio-2.1.13/MANIFEST.in +0 -18
  27. libusbsio-2.1.13/libusbsio/bin/linux_x86_64/libusbsio.so +0 -0
  28. libusbsio-2.1.13/libusbsio/bin/x64/libusbsio.dll +0 -0
  29. libusbsio-2.1.13/license/SoftwareContentRegister.txt +0 -27
  30. libusbsio-2.1.13/pyproject.toml +0 -6
  31. libusbsio-2.1.13/setup.py +0 -56
  32. libusbsio-2.1.13/test/test_base.py +0 -84
  33. {libusbsio-2.1.13 → libusbsio-2.2.0}/examples/spi.py +0 -0
  34. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/__main__.py +0 -0
  35. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/LICENSE-hidapi-bsd.txt +0 -0
  36. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/linux_aarch64/libusbsio.so +0 -0
  37. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/linux_armv7l/libusbsio.so +0 -0
  38. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio/bin/linux_i686/libusbsio.so +0 -0
  39. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio.egg-info/dependency_links.txt +0 -0
  40. {libusbsio-2.1.13 → libusbsio-2.2.0}/libusbsio.egg-info/top_level.txt +0 -0
  41. {libusbsio-2.1.13 → libusbsio-2.2.0}/license/LICENSE-hidapi-bsd.txt +0 -0
  42. {libusbsio-2.1.13 → libusbsio-2.2.0}/setup.cfg +0 -0
  43. {libusbsio-2.1.13 → libusbsio-2.2.0}/test/__init__.py +0 -0
  44. {libusbsio-2.1.13 → libusbsio-2.2.0}/test/test_30_gpio.py +0 -0
@@ -0,0 +1,2 @@
1
+ The libusbsio Python package and related binaries is released under BSD-3-Clause License.
2
+ See the 'license' folder for related license files and SBOM-libusbsio.spdx.json.
@@ -0,0 +1,8 @@
1
+ recursive-include libusbsio/bin *
2
+
3
+ include license/SBOM-libusbsio.spdx.json
4
+ include license/BSD-3-clause.txt
5
+ include license/LICENSE-hidapi-bsd.txt
6
+
7
+ global-exclude *.py[cod]
8
+ prune __pycache__
@@ -1,28 +1,26 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: libusbsio
3
- Version: 2.1.13
3
+ Version: 2.2.0
4
4
  Summary: Python wrapper around NXP LIBUSBSIO library
5
- Author: Michal Hanak
6
- Author-email: michal.hanak@nxp.com
7
- License: BSD-3-Clause
8
- Project-URL: NXP LIBUSBSIO Home, https://www.nxp.com/design/software/development-software/library-for-windows-macos-and-ubuntu-linux:LIBUSBSIO
9
- Project-URL: MCULink Pro, https://www.nxp.com/design/microcontrollers-developer-resources/mcu-link-pro-debug-probe:MCU-LINK-PRO
10
- Project-URL: LPCLink2, https://www.nxp.com/design/microcontrollers-developer-resources/lpc-microcontroller-utilities/lpc-link2:OM13054
5
+ Author-email: Michal Hanak <michal.hanak@nxp.com>
6
+ License-Expression: BSD-3-Clause
7
+ Project-URL: Homepage, https://www.nxp.com/libusbsio
8
+ Project-URL: NXP LIBUSBSIO Home, https://www.nxp.com/libusbsio
9
+ Project-URL: MCU-Link Pro, https://www.nxp.com/mculink
10
+ Project-URL: LPCLink2, https://www.nxp.com/lpclink2
11
11
  Keywords: LIBUSBSIO,USBSIO,SPI,I2C,GPIO
12
- Platform: Windows
13
- Platform: Linux
14
- Platform: Mac OSX
15
12
  Classifier: Programming Language :: Python :: 3
16
13
  Classifier: Operating System :: POSIX :: Linux
17
14
  Classifier: Operating System :: Microsoft :: Windows
18
15
  Classifier: Operating System :: MacOS :: MacOS X
19
- Classifier: License :: OSI Approved :: BSD License
20
16
  Classifier: Topic :: Scientific/Engineering
21
17
  Classifier: Topic :: Software Development :: Embedded Systems
22
18
  Classifier: Topic :: System :: Hardware
23
19
  Classifier: Topic :: Utilities
24
20
  Requires-Python: >=3.6
25
21
  Description-Content-Type: text/markdown
22
+ License-File: LICENSE.txt
23
+ Dynamic: license-file
26
24
 
27
25
  # Python wrapper for NXP libusbsio binary library
28
26
 
@@ -55,7 +53,7 @@ python -m pip install libusbsio
55
53
  Use the following `pip` command to install the libusbsio module from
56
54
  the local NXP LIBUSBSIO installation package available at www.nxp.com:
57
55
  ```
58
- python -m pip install dist/libusbsio-2.1.13-py3-none-any.whl
56
+ python -m pip install dist/libusbsio-2.2.0-py3-none-any.whl
59
57
  ```
60
58
 
61
59
  ## Running example code
@@ -120,6 +118,10 @@ test\test_30_gpio.py ......s.
120
118
  ```
121
119
 
122
120
  ## History
121
+ ### v2.2.0 - October 2025
122
+ - Add OpenBySerial and OpenByPath more robust calls, immune to index reordering upon re-enumeration.
123
+ - Enumerated devices list remains valid after device close; GetNumPorts re-enumeration is no longer needed
124
+ - Multiple LIBUSBSIO objects may be open and used simultaneously, one for each connected device.
123
125
  ### v2.1.13 - October 2024
124
126
  - Fix HID_API Windows enumeration to avoid accidental duplicate device enumeration.
125
127
  ### v2.1.12 - January 2023
@@ -141,4 +143,4 @@ test\test_30_gpio.py ......s.
141
143
  - The initial Python libusbsio library wrapper release supporting USBSIO library v2.1
142
144
 
143
145
  ____
144
- Copyright NXP 2021-2024
146
+ Copyright NXP 2021-2025
@@ -29,7 +29,7 @@ python -m pip install libusbsio
29
29
  Use the following `pip` command to install the libusbsio module from
30
30
  the local NXP LIBUSBSIO installation package available at www.nxp.com:
31
31
  ```
32
- python -m pip install dist/libusbsio-2.1.13-py3-none-any.whl
32
+ python -m pip install dist/libusbsio-2.2.0-py3-none-any.whl
33
33
  ```
34
34
 
35
35
  ## Running example code
@@ -94,6 +94,10 @@ test\test_30_gpio.py ......s.
94
94
  ```
95
95
 
96
96
  ## History
97
+ ### v2.2.0 - October 2025
98
+ - Add OpenBySerial and OpenByPath more robust calls, immune to index reordering upon re-enumeration.
99
+ - Enumerated devices list remains valid after device close; GetNumPorts re-enumeration is no longer needed
100
+ - Multiple LIBUSBSIO objects may be open and used simultaneously, one for each connected device.
97
101
  ### v2.1.13 - October 2024
98
102
  - Fix HID_API Windows enumeration to avoid accidental duplicate device enumeration.
99
103
  ### v2.1.12 - January 2023
@@ -115,4 +119,4 @@ test\test_30_gpio.py ......s.
115
119
  - The initial Python libusbsio library wrapper release supporting USBSIO library v2.1
116
120
 
117
121
  ____
118
- Copyright NXP 2021-2024
122
+ Copyright NXP 2021-2025
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  #
3
- # Copyright 2021 NXP
3
+ # Copyright 2021,2025 NXP
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  #
6
6
  # NXP USBSIO Library - HID devices enumeration example
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  #
3
- # Copyright 2021 NXP
3
+ # Copyright 2021, 2025 NXP
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  #
6
6
  # NXP USBSIO Library - I2C example code
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  #
3
- # Copyright 2021-2022 NXP
3
+ # Copyright 2021-2022,2025 NXP
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  #
6
6
  # NXP USBSIO Library - I2C example code
@@ -21,10 +21,10 @@ from libusbsio import *
21
21
  logging.basicConfig()
22
22
 
23
23
  # example on how to load DLL from a specific directory
24
- #sio = LIBUSBSIO(r"..\..\bin_debug\x64", loglevel=logging.DEBUG)
24
+ #sio = usbsio(r"..\..\bin_debug\x64", loglevel=logging.DEBUG)
25
25
 
26
26
  # load DLL from default directory
27
- sio = LIBUSBSIO()
27
+ sio = usbsio()
28
28
 
29
29
  ############################################################################
30
30
  ############################################################################
@@ -34,6 +34,8 @@ sio = LIBUSBSIO()
34
34
  numports = sio.GetNumPorts()
35
35
  print("SIO ports = %d" % numports)
36
36
 
37
+ all_devices=[]
38
+
37
39
  if not numports:
38
40
  print("No USBSIO device found")
39
41
 
@@ -46,11 +48,28 @@ for i in range(0, numports):
46
48
  print(f" HID product: {info.manufacturer_string} {info.product_string}")
47
49
  print(f" HID serial: {info.serial_number}")
48
50
  print(f" HID path: {info.path}")
51
+ all_devices.insert(0, (i, info.serial_number, info.path) )
49
52
  print(" LIB version = '%s'" % sio.GetVersion())
50
53
  print(" I2C ports = %d" % sio.GetNumI2CPorts())
51
54
  print(" SPI ports = %d" % sio.GetNumSPIPorts())
52
55
  print(" Max data size = %d" % sio.GetMaxDataSize())
53
56
  sio.Close()
54
- # re-enumerate after closing port
55
- sio.GetNumPorts()
57
+
58
+ print("\nTest re-open all devices using serial numbers:")
59
+ for d in all_devices:
60
+ print(f"Opening serial_number {d[1]} (was device #{d[0]})")
61
+ if sio.OpenBySerial(d[1]):
62
+ print(f" ...success: {sio.GetVersion()}")
63
+ sio.Close()
64
+ else:
65
+ print(f" ...failed")
66
+
67
+ print("\nTest re-open all devices using USB HID paths:")
68
+ for d in all_devices:
69
+ print(f"Opening path {d[2]} (was device #{d[0]})")
70
+ if sio.OpenByPath(d[2]):
71
+ print(f" ...success: {sio.GetVersion()}")
72
+ sio.Close()
73
+ else:
74
+ print(f" ...failed")
56
75
 
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env python3
2
2
  #
3
- # Copyright 2021-2024 NXP
3
+ # Copyright 2021-2025 NXP
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  #
6
6
  # NXP USBSIO Library to control SPI, I2C and GPIO bus over USB
7
7
  #
8
- __version__ = '2.1.13'
8
+ __version__ = '2.2.0'
9
9
  __title__ = 'usblibsio'
10
10
  __author__ = 'NXP Semiconductors'
11
- __copyright__ = 'Copyright NXP 2021-2024'
11
+ __copyright__ = 'Copyright NXP 2021-2025'
12
12
  __license__ = 'BSD-3-Clause'
13
13
  __url__ = 'https://www.nxp.com/design/software/development-software/library-for-windows-macos-and-ubuntu-linux:LIBUSBSIO'
14
14
  __description__ = 'Python interface for the NXP USBSIO Library version %s' % __version__
15
- __long_description__ = '''LIBUSBSIO: The NXP USBSIO Library version %s
15
+ __long_description__ = '''LIBUSBSIO: The NXP USBSIO Library version %s.
16
16
  This module implements a Python wrapper around the NXP USBSIO Library enabling to access SPI or
17
17
  I2C bus and GPIO ports over a USB interface of the NXP LPC-link2 and MCU-Link devices.
18
18
  ''' % __version__
@@ -1,4 +1,4 @@
1
- Copyright 2021 NXP
1
+ Copyright 2021-2025 NXP
2
2
 
3
3
  Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
4
4
 
@@ -0,0 +1,95 @@
1
+ {
2
+ "SPDXID": "SPDXRef-DOCUMENT",
3
+ "spdxVersion": "SPDX-2.3",
4
+ "creationInfo": {
5
+ "created": "2025-10-31T10:12:29Z",
6
+ "creators": [
7
+ "Organization: NXP"
8
+ ],
9
+ "licenseListVersion": "3.20"
10
+ },
11
+ "name": "libusbsio-2.2.0",
12
+ "dataLicense": "CC0-1.0",
13
+ "documentNamespace": "https://nxp.com/spdx/79c03a43-7a2b-4947-b1c4-8d87e24adb43",
14
+ "packages": [
15
+ {
16
+ "SPDXID": "SPDXRef-package-16ddf628-ffe8-4a50-a37f-4ac21026fc7b",
17
+ "name": "hidapi",
18
+ "versionInfo": "0.11.2",
19
+ "licenseConcluded": "BSD-3-Clause",
20
+ "licenseDeclared": "(BSD-3-Clause OR GPL-3.0-or-later)",
21
+ "homepage": "http://www.signal11.us/oss/hidapi/",
22
+ "downloadLocation": "https://pypi.org/project/hidapi/0.11.2",
23
+ "originator": "Organization: pypi",
24
+ "supplier": "NOASSERTION",
25
+ "externalRefs": [
26
+ {
27
+ "referenceCategory": "PACKAGE-MANAGER",
28
+ "referenceLocator": "pkg:pypi/hidapi@0.11.2",
29
+ "referenceType": "purl"
30
+ },
31
+ {
32
+ "referenceCategory": "OTHER",
33
+ "referenceLocator": "c8918c0e-682f-457a-9eaa-4e38a17a5c10",
34
+ "referenceType": "BlackDuck-ComponentOrigin"
35
+ }
36
+ ],
37
+ "filesAnalyzed": false,
38
+ "licenseComments": "Multiple license: license chosen BSD-3-Clause"
39
+ },
40
+ {
41
+ "SPDXID": "SPDXRef-package-79c03a43-7a2b-4947-b1c4-8d87e24adb43",
42
+ "name": "libusbsio",
43
+ "versionInfo": "2.2.0",
44
+ "licenseConcluded": "(BSD-3-Clause)",
45
+ "licenseDeclared": "(BSD-3-Clause)",
46
+ "downloadLocation": "https://pypi.org/project/libusbsio/ https://www.nxp.com/design/design-center/software/development-software/libusbsio-host-library-for-usb-enabled-mcus:LIBUSBSIO",
47
+ "originator": "Organization: NXP",
48
+ "supplier": "NOASSERTION",
49
+ "externalRefs": [],
50
+ "filesAnalyzed": false
51
+ },
52
+ {
53
+ "SPDXID": "SPDXRef-package-8c673b9b-215e-40f5-bf01-40c6bfc02b03",
54
+ "name": "libhidapi-hidraw0",
55
+ "versionInfo": "0.11.2",
56
+ "licenseConcluded": "BSD-3-Clause",
57
+ "licenseDeclared": "(BSD-3-Clause OR GPL-3.0-or-later)",
58
+ "homepage": "http://www.signal11.us/oss/hidapi/",
59
+ "downloadLocation": "http://archive.ubuntu.com/ubuntu/ubuntu/pool/universe/h/hidapi",
60
+ "originator": "Organization: ubuntu",
61
+ "supplier": "NOASSERTION",
62
+ "externalRefs": [
63
+ {
64
+ "referenceCategory": "PACKAGE-MANAGER",
65
+ "referenceLocator": "pkg:deb/ubuntu/hidapi@0.11.2-1",
66
+ "referenceType": "purl"
67
+ },
68
+ {
69
+ "referenceCategory": "OTHER",
70
+ "referenceLocator": "ac0becc4-29d8-469d-a6fa-d42a0c88ae4b",
71
+ "referenceType": "BlackDuck-ComponentOrigin"
72
+ }
73
+ ],
74
+ "filesAnalyzed": false,
75
+ "licenseComments": "Multiple license: license chosen BSD-3-Clause"
76
+ }
77
+ ],
78
+ "relationships": [
79
+ {
80
+ "spdxElementId": "SPDXRef-package-79c03a43-7a2b-4947-b1c4-8d87e24adb43",
81
+ "relationshipType": "CONTAINS",
82
+ "relatedSpdxElement": "SPDXRef-package-16ddf628-ffe8-4a50-a37f-4ac21026fc7b"
83
+ },
84
+ {
85
+ "spdxElementId": "SPDXRef-DOCUMENT",
86
+ "relationshipType": "DESCRIBES",
87
+ "relatedSpdxElement": "SPDXRef-package-79c03a43-7a2b-4947-b1c4-8d87e24adb43"
88
+ },
89
+ {
90
+ "spdxElementId": "SPDXRef-package-79c03a43-7a2b-4947-b1c4-8d87e24adb43",
91
+ "relationshipType": "CONTAINS",
92
+ "relatedSpdxElement": "SPDXRef-package-8c673b9b-215e-40f5-bf01-40c6bfc02b03"
93
+ }
94
+ ]
95
+ }
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  #
3
- # Copyright 2021-2022 NXP
3
+ # Copyright 2021-2022,2025 NXP
4
4
  # SPDX-License-Identifier: BSD-3-Clause
5
5
  #
6
6
  # NXP USBSIO Library to control SPI, I2C and GPIO bus over USB
@@ -15,6 +15,8 @@ from ctypes import (CDLL, POINTER, Structure, c_char_p, c_int32, c_uint8,
15
15
  c_uint16, c_uint32, c_void_p, c_wchar_p)
16
16
  from typing import Generator, List, Tuple
17
17
 
18
+ def _hex(n):
19
+ return hex(n) if n is not None else "None"
18
20
 
19
21
  class LibUsbStructure(Structure):
20
22
  @property
@@ -41,10 +43,89 @@ class LIBUSBSIO_Exception(Exception):
41
43
  message = "LIBUSBSIO: " + message
42
44
  super().__init__(message)
43
45
 
46
+ class LIBUSBSIO_DllManager(object):
47
+ """# This object is used as a singleton by LIBUSBSIO instances, to manage DLLs.
48
+ This object counts references to DLLs used by LIBUSBSIO instances and unloads
49
+ them when no more clients use it.
50
+ """
51
+ def __init__(self):
52
+ '''LIBUSBSIO_DLL class constructor'''
53
+ self._instances = {}
54
+
55
+ class Record:
56
+ '''Data record managed for each instance
57
+ '''
58
+ def __init__(self, cdll:'CDLL'):
59
+ self.__dict__.update({ "cdll":cdll, "used":1 })
60
+
61
+ def __del__(self):
62
+ '''LIBUSBSIO_DLL class destructor.
63
+ Takes care about cleaning up remaining DLLs
64
+ '''
65
+ for i in self._instances:
66
+ self._cleanup_cdll(self._instances[i].cdll)
67
+
68
+ def LoadDLL(self, dllpath:str) -> 'CDLL|None':
69
+ '''Get DLL handle, either it was loaded earlier or it is the first time now'''
70
+ dll = None
71
+ if dllpath in self._instances:
72
+ # DLL already used, increment usage count
73
+ record = self._instances[dllpath]
74
+ record.used += 1
75
+ dll = record.cdll
76
+ else:
77
+ # DLL being loaded for the first time, create its record
78
+ dll = CDLL(dllpath)
79
+ if dll:
80
+ record = LIBUSBSIO_DllManager.Record(dll)
81
+ self._instances[dllpath] = record
82
+ # note that dll may be None if library load failed
83
+ return dll
84
+
85
+ def FreeDLL(self, cdll:'CDLL') -> bool:
86
+ '''Decrement usage counter on CDLL object and free library if zero'''
87
+ unloaded = False
88
+ # Find the DLL's record
89
+ for p in self._instances:
90
+ record = self._instances[p]
91
+ if cdll is record.cdll:
92
+ # Decrement usage count
93
+ record.used -= 1
94
+ if record.used == 0:
95
+ # Free DLL if usage count reached zero
96
+ self._cleanup_cdll(cdll)
97
+ del self._instances[p]
98
+ unloaded = 1
99
+ break
100
+ return unloaded
101
+
102
+ def _cleanup_cdll(self, cdll:'CDLL'):
103
+ '''Physically unload the LIBUSBSIO DLL library'''
104
+ try:
105
+ # Versions v2.2 and later has a LibCleanup method
106
+ cleanup = cdll.LPCUSBSIO_LibCleanup
107
+ cleanup.argtypes = []
108
+ cleanup.restype = c_int32
109
+ cleanup()
110
+ except Exception as e:
111
+ # Ignore if LibCleanup does not exist or fails
112
+ pass
113
+ # Unload the library object
114
+ del cdll
115
+
116
+ # the LIBUSBSIO_DllManager singleton object used by all LIBUSBSIO instances
117
+ _the_libusbsio_dll = LIBUSBSIO_DllManager()
118
+
44
119
  class LIBUSBSIO(object):
45
- """# Class encapsulating functionality of the NXP USBSIO binary library.
46
- The library enables to access SPI or I2C bus and GPIO ports over a USB interface
47
- of the NXP LPC-link2 and MCU-Link bridge devices.
120
+ """# Class encapsulating functionality of the NXP USBSIO device port.
121
+
122
+ The object enables to access SPI or I2C bus and GPIO ports over a USB interface
123
+ of the NXP LPC-link2 and MCU-Link bridge devices. Multiple object
124
+ can be created simultaneously to access different USBSIO devices.
125
+
126
+ Note: The USB devices are not open in exclusive mode, so using multiple
127
+ LIBUSBSIO instances to access the same device is technically possible
128
+ but not recommended.
48
129
  """
49
130
 
50
131
  # platforms
@@ -57,6 +138,7 @@ class LIBUSBSIO(object):
57
138
  ERR_SYNCHRONIZATION = -3 # Thread Synchronization error.
58
139
  ERR_MEM_ALLOC = -4 # Memory allocation error.
59
140
  ERR_MUTEX_CREATE = -5 # Mutex creation error.
141
+ ERR_FORCED_CLEANUP = -6 # Some objects might have been in use during cleanup.
60
142
 
61
143
  # I2C hardware interface errors
62
144
  ERR_FATAL = -0x11 # Fatal error occurred
@@ -170,7 +252,7 @@ class LIBUSBSIO(object):
170
252
 
171
253
  # search for the DLL
172
254
  def _lookup_dll_path(subdir: str, dllname: str):
173
- ''' search for the DLL specified by a sub-directoruy and DLL name'''
255
+ ''' search for the DLL specified by a sub-directory and DLL name'''
174
256
  def probe(*parts):
175
257
  p = os.path.join(*parts)
176
258
  return p if os.path.isfile(p) else None
@@ -199,7 +281,6 @@ class LIBUSBSIO(object):
199
281
 
200
282
  self._dll = None
201
283
  self._dllpath:str = None
202
- self._devIx:int = None
203
284
  self._ports_open:List[int] = []
204
285
  self._h = None
205
286
  self._vidpid = (0,0)
@@ -212,7 +293,7 @@ class LIBUSBSIO(object):
212
293
  if self._h:
213
294
  self.Close()
214
295
  if self._dll:
215
- del self._dll
296
+ _the_libusbsio_dll.FreeDLL(self._dll)
216
297
  self._dll = None
217
298
  self._dllpath = None
218
299
  self.logger.info("SIO library unloaded")
@@ -269,7 +350,7 @@ class LIBUSBSIO(object):
269
350
  dllname = "libusbsio.dylib"
270
351
  packing = 8
271
352
  else:
272
- ex = LIBUSBSIO_Exception("Unknown platform to load proper library.")
353
+ ex = LIBUSBSIO_Exception("Unknown platform, cannot load library.")
273
354
  if raiseOnError:
274
355
  raise ex
275
356
  return ex
@@ -299,8 +380,7 @@ class LIBUSBSIO(object):
299
380
 
300
381
  self.logger.info("Loading SIO library: %s" % dllpath)
301
382
  self._dllpath = dllpath
302
- self._dll = CDLL(dllpath)
303
- self._devIx = None
383
+ self._dll = _the_libusbsio_dll.LoadDLL(dllpath)
304
384
  self._h = None
305
385
 
306
386
  if not self._dll:
@@ -441,6 +521,22 @@ class LIBUSBSIO(object):
441
521
  self._GPIO_ConfigIOPin.argtypes = [c_void_p, c_uint8, c_uint8, c_uint32]
442
522
  self._GPIO_ConfigIOPin.restype = c_int32
443
523
 
524
+ # methods added in LIBUSBSIO v2.2, gracefully ignore if missing
525
+ try:
526
+ self._OpenBySerial = self._dll.LPCUSBSIO_OpenBySerial
527
+ self._OpenBySerial.argtypes = [c_wchar_p]
528
+ self._OpenBySerial.restype = c_void_p
529
+ except:
530
+ self._OpenBySerial = lambda x: 0
531
+
532
+ try:
533
+ self._OpenByPath = self._dll.LPCUSBSIO_OpenByPath
534
+ self._OpenByPath.argtypes = [c_char_p]
535
+ self._OpenByPath.restype = c_void_p
536
+ except:
537
+ self._OpenByPath = lambda x: 0
538
+
539
+ # low-level HIDAPI interface
444
540
  if 1:
445
541
  self._HIDAPI_Enumerate = self._dll.HIDAPI_Enumerate
446
542
  self._HIDAPI_Enumerate.argtypes = [c_uint32,c_uint32,c_int32]
@@ -546,7 +642,7 @@ class LIBUSBSIO(object):
546
642
  @need_dll_loaded
547
643
  def GetNumPorts(self, vidpids:'list[tuple[int,int]]' = None) -> int:
548
644
  '''# Get number of USBSIO ports
549
- Gets the number of USBSIO ports that are available on the controller. Multiple PID+VID tuples
645
+ Gets the number of USBSIO ports that are available on the controller. Multiple VID+PID tuples
550
646
  may be specified to search multiple types of devices. The first device in the list which is detected
551
647
  is the one which will be used and which returns the number of its communication ports.
552
648
 
@@ -609,10 +705,60 @@ class LIBUSBSIO(object):
609
705
  ## Returns
610
706
  Boolean True if open was successful. False if not successful.
611
707
  '''
612
- self.logger.info("Opening SIODevice%d" % dev)
708
+ self.Close()
709
+ self.logger.info("Opening SIODevice index %d" % dev)
613
710
  self._h = self._Open(dev)
614
- self._devIx = dev
615
- self.logger.debug("SIODevice%d Open returns %s" % (dev, self._h))
711
+ if self._h:
712
+ self.logger.info("Open(%d) returns %s" % (dev, _hex(self._h)))
713
+ else:
714
+ self.logger.error("Open(%d) failed." % dev)
715
+ self._ports_open = []
716
+ return bool(self._h)
717
+
718
+ @need_dll_loaded
719
+ def OpenBySerial(self, serial:str) -> bool:
720
+ '''# Open USBSIO port by looking for a device identified by serial number
721
+ This function looks for USBSIO device identified by serial number and opens this device.
722
+ User still needs to call GetNumPorts to perform device enumeration and VID/PID filtering.
723
+ The port handle will be closed automatically in this object's destructor.
724
+
725
+ ## Args
726
+ - `serial` - Serial number device identifier.
727
+
728
+ ## Returns
729
+ Boolean True if open was successful. False if not successful.
730
+ '''
731
+ self.Close()
732
+ self.logger.info("Opening SIODevice serial number '%s'" % serial)
733
+ self._h = self._OpenBySerial(serial)
734
+ if self._h:
735
+ self.logger.info("OpenBySerial('%s') returns %s" % (serial, _hex(self._h)))
736
+ else:
737
+ self.logger.error("OpenBySerial('%s') failed." % serial)
738
+ self._ports_open = []
739
+ return bool(self._h)
740
+
741
+ @need_dll_loaded
742
+ def OpenByPath(self, hid_path:str) -> bool:
743
+ '''# Open USBSIO port from a device specified by USB HID device path. This is the
744
+ only Open function which does not require the GetNumPorts device enumeration
745
+ to be called prior port opening. Note that USB device path is a platform
746
+ specific string. You should not store the path value permanently.
747
+ The port handle will be closed automatically in this object's destructor.
748
+
749
+ ## Args
750
+ - `hid_path` - USB HID device path.
751
+
752
+ ## Returns
753
+ Boolean True if open was successful. False if not successful.
754
+ '''
755
+ self.Close()
756
+ self.logger.info("Opening SIODevice at path '%s'" % hid_path)
757
+ self._h = self._OpenByPath(hid_path)
758
+ if self._h:
759
+ self.logger.info("OpenByPath('%s') returns %s" % (hid_path, _hex(self._h)))
760
+ else:
761
+ self.logger.error("OpenByPath('%s') failed." % hid_path)
616
762
  self._ports_open = []
617
763
  return bool(self._h)
618
764
 
@@ -627,9 +773,9 @@ class LIBUSBSIO(object):
627
773
  ret = 1
628
774
  if self._h:
629
775
  ret = self._Close(self._h)
630
- self.logger.info("Closed SIODevice%d code=%d" % (self._devIx, ret))
776
+ self.logger.info("Closed SIODevice (handle=%s) code=%d" % (_hex(self._h), ret))
631
777
  self._h = None
632
- self._devIx = None
778
+
633
779
  return ret
634
780
 
635
781
  @need_dll_open
@@ -1374,7 +1520,7 @@ class LIBUSBSIO(object):
1374
1520
  self.logger.info("Opening HID device at path: '%s'" % path)
1375
1521
  self._h = self._sio._HIDAPI_DeviceOpen(path)
1376
1522
  if self._h:
1377
- self.logger.info("HID device %d is now open" % self._h)
1523
+ self.logger.info("HID device is now open as handle %s" % _hex(self._h))
1378
1524
  else:
1379
1525
  self.logger.error("HID device '%s' opening failed." % path)
1380
1526
  return self._h != 0
@@ -1390,7 +1536,7 @@ class LIBUSBSIO(object):
1390
1536
  h = self._h
1391
1537
  self._h = None
1392
1538
  ret = self._sio._HIDAPI_DeviceClose(h)
1393
- self.logger.info("HID device %d closed" % h)
1539
+ self.logger.info("HID device %s closed" % _hex(h))
1394
1540
  return ret == 0
1395
1541
 
1396
1542
  @need_device_open
@@ -1471,24 +1617,15 @@ class LIBUSBSIO(object):
1471
1617
  return dev
1472
1618
 
1473
1619
 
1474
- # the LIBUSBSIO singleton object
1475
- _LIBUSBSIO_SINGLETON:LIBUSBSIO = None
1476
-
1477
1620
  def usbsio(dllpath:str=None, loglevel:int=logging.NOTSET, autoload=True) -> LIBUSBSIO:
1478
- '''# LIBUSBSIO singleton object
1479
- The returned instance acts as kind-of 'singleton' object, created
1480
- upon the first call of this function. All subsequent calls returns
1481
- the same instance.
1621
+ '''# LIBUSBSIO object factory. Since v2.2 it is a simple object creator as we now
1622
+ support multiple USBSIO devices to be open simultaneously. Older versions
1623
+ of this factory were returning a singleton object, but this is no longer needed.
1482
1624
 
1483
1625
  ## Args
1484
- All arguments are passed to LIBUSBSIO constructor when the instance
1485
- is created for the first time. The arguments are ignored when the instance
1486
- already exists.
1626
+ All arguments are passed to LIBUSBSIO constructor.
1487
1627
  - `dllpath` Path to LIBUSBSIO dynamic library. Use None to autodetect based on operating system.
1488
1628
  - `loglevel` Internal logging level, defaults to logging.NOTSET.
1489
1629
  - `autoload` Set to load the DLL library automatically.
1490
1630
  '''
1491
- global _LIBUSBSIO_SINGLETON
1492
- if not _LIBUSBSIO_SINGLETON:
1493
- _LIBUSBSIO_SINGLETON = LIBUSBSIO(dllpath=dllpath, loglevel=loglevel, autoload=autoload)
1494
- return _LIBUSBSIO_SINGLETON
1631
+ return LIBUSBSIO(dllpath=dllpath, loglevel=loglevel, autoload=autoload)