1010
1111- Turn digital output on and off
1212"""
13+
1314import usb .core
1415import usb .util
1516
@@ -23,46 +24,79 @@ def __init__(self, **args):
2324 self ._dev = usb .core .find (** args )
2425 if self ._dev is None :
2526 raise ValueError ("Device not found" )
27+
28+ if self ._dev .idVendor == 0x16C0 :
29+ self .set_output = self .set_output_dcttech
30+ self .get_output = self .get_output_dcttech
31+ elif self ._dev .idVendor == 0x5131 :
32+ self .set_output = self .set_output_lcus
33+ self .get_output = self .get_output_lcus
34+ else :
35+ raise ValueError (f"Unknown vendor/protocol for VID { self ._dev .idVendor :x} " )
36+
2637 if self ._dev .is_kernel_driver_active (0 ):
2738 self ._dev .detach_kernel_driver (0 )
2839
29- def set_output (self , number , status ):
40+ def set_output_dcttech (self , number , status ):
3041 assert 1 <= number <= 8
3142 req = [0xFF if status else 0xFD , number ]
3243 self ._dev .ctrl_transfer (
3344 usb .util .CTRL_TYPE_CLASS | usb .util .CTRL_RECIPIENT_DEVICE | usb .util .ENDPOINT_OUT ,
3445 SET_REPORT ,
35- (REPORT_TYPE_FEATURE << 8 ) | 0 , # no report ID
46+ (REPORT_TYPE_FEATURE << 8 ) | 0 , # no report ID
3647 0 ,
37- req , # payload
48+ req , # payload
3849 )
3950
40- def get_output (self , number ):
51+ def get_output_dcttech (self , number ):
4152 assert 1 <= number <= 8
4253 resp = self ._dev .ctrl_transfer (
4354 usb .util .CTRL_TYPE_CLASS | usb .util .CTRL_RECIPIENT_DEVICE | usb .util .ENDPOINT_IN ,
4455 GET_REPORT ,
45- (REPORT_TYPE_FEATURE << 8 ) | 0 , # no report ID
56+ (REPORT_TYPE_FEATURE << 8 ) | 0 , # no report ID
4657 0 ,
47- 8 , # size
58+ 8 , # size
4859 )
49- return bool (resp [7 ] & (1 << (number - 1 )))
60+ return bool (resp [7 ] & (1 << (number - 1 )))
61+
62+ def set_output_lcus (self , number , status ):
63+ assert 1 <= number <= 8
64+ ep_in = self ._dev [0 ][(0 , 0 )][0 ]
65+ ep_out = self ._dev [0 ][(0 , 0 )][1 ]
66+ req = [0xA0 , number , 0x01 if status else 0x00 , 0x00 ]
67+ req [3 ] = sum (req ) & 0xFF
68+ ep_out .write (req )
69+ ep_in .read (64 )
70+
71+ def get_output_lcus (self , number ):
72+ assert 1 <= number <= 8
73+ # we have no information on how to read the current value
74+ return False
5075
5176 def __del__ (self ):
5277 usb .util .release_interface (self ._dev , 0 )
5378
5479
80+ _relays = {}
81+
82+
83+ def _get_relay (busnum , devnum ):
84+ if (busnum , devnum ) not in _relays :
85+ _relays [(busnum , devnum )] = USBHIDRelay (bus = busnum , address = devnum )
86+ return _relays [(busnum , devnum )]
87+
88+
5589def handle_set (busnum , devnum , number , status ):
56- relay = USBHIDRelay ( bus = busnum , address = devnum )
90+ relay = _get_relay ( busnum , devnum )
5791 relay .set_output (number , status )
5892
5993
6094def handle_get (busnum , devnum , number ):
61- relay = USBHIDRelay ( bus = busnum , address = devnum )
95+ relay = _get_relay ( busnum , devnum )
6296 return relay .get_output (number )
6397
6498
6599methods = {
66- ' set' : handle_set ,
67- ' get' : handle_get ,
100+ " set" : handle_set ,
101+ " get" : handle_get ,
68102}
0 commit comments