forked from ryancdotorg/gub211
-
Notifications
You must be signed in to change notification settings - Fork 0
/
gub211.py
executable file
·106 lines (83 loc) · 2.88 KB
/
gub211.py
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
#!/usr/bin/env python3
from sys import exit, argv, stdin, stderr, stdout, version_info
from functools import partial
eprint = partial(print, file=stderr)
import usb.core
import usb.util
'''
user space utility to grab the device connected to a IOGEAR GUB211 auto
sharing usb switch. The device shows up with VID=0x2101, PID=0x0231. Since
that vendor id belongs to actionstar, I would expect this program to also
work with ActionStar's SW-221A and SW-241A, but I haven't tested it.
This will either need to run as root or you will need to do udev magic to
set the permissions to allow access to the user you're going to run it as.
'''
def _ctrl_transfer(dev, *args):
try:
# detatch kernel driver
for n in (0, 1):
if dev.is_kernel_driver_active(n):
dev.detach_kernel_driver(n)
# copypasta from the pyusb 1.0 tutorial, with the mistakes fixed
dev.set_configuration()
cfg = dev.get_active_configuration()
if_num = cfg[(0,0)].bInterfaceNumber
intf = usb.util.find_descriptor(
cfg,
bInterfaceNumber = if_num,
bAlternateSetting = usb.control.get_interface(dev, if_num),
)
# claim the interface so we can talk to it
usb.util.claim_interface(dev, intf)
# send command
dev.ctrl_transfer(*args)
# release
usb.util.release_interface(dev, intf)
usb.util.dispose_resources(dev)
return True
except:
dev.reset()
return False
def switch(dev):
# send the magic 'switch to me' command, found by sniffing the USB bus
# bmRequestType 0b0_01_00001 (dir: host to device, type: class, recip: interface)
# bRequest 0x09 HID_SET_REPORT?
# wValue 0x0203
# wIndex 0x0001
_ctrl_transfer(dev, 0x21, 0x09, 0x0203, 0x0001, "\x03\x5d\x42\x00\x00")
def find():
return list(usb.core.find(find_all=True, idVendor=0x2101, idProduct=0x0231))
def path(dev):
return f'{dev.bus}:{"/".join(map(str, dev.port_numbers))}'
def _match(path):
bus, _, ports = path.partition(':')
if not (bus and ports):
return None, None
return int(bus), tuple(map(int, ports.split('/')))
def main(arg=None):
devs = find()
if arg == 'list':
for dev in devs:
print('device at:', path(dev))
elif not len(devs):
eprint('no devices found')
return -1
elif arg == 'only':
if len(devs) != 1:
eprint('multiple devices found')
return -1
switch(devs[0])
elif arg == 'first' or arg is None:
switch(devs[0])
else:
bus, ports = _match(arg)
for dev in devs:
if dev.bus == bus and dev.port_numbers == ports:
switch(dev)
return 0
eprint('no matching device')
return -1
return 0
if __name__ == '__main__':
args = argv[1:]
exit(main(*args))