]> glassweightruler.freedombox.rocks Git - waydroid.git/blob - tools/helpers/drivers.py
drivers: Allocate binder nodes dynamically
[waydroid.git] / tools / helpers / drivers.py
1 # Copyright 2021 Erfan Abdi
2 # SPDX-License-Identifier: GPL-3.0-or-later
3 import logging
4 import os
5 import glob
6 import fcntl
7 import struct
8 import tools.config
9 import tools.helpers.run
10
11
12 BINDER_DRIVERS = [
13 "anbox-binder",
14 "puddlejumper",
15 "binder"
16 ]
17 VNDBINDER_DRIVERS = [
18 "anbox-vndbinder",
19 "vndpuddlejumper",
20 "vndbinder"
21 ]
22 HWBINDER_DRIVERS = [
23 "anbox-hwbinder",
24 "hwpuddlejumper",
25 "hwbinder"
26 ]
27
28
29 def isBinderfsLoaded(args):
30 with open("/proc/filesystems", "r") as handle:
31 for line in handle:
32 words = line.split()
33 if len(words) >= 2 and words[1] == "binder":
34 return True
35
36 return False
37
38 def allocBinderNodes(args, binder_dev_nodes):
39 NRBITS = 8
40 TYPEBITS = 8
41 SIZEBITS = 14
42 NRSHIFT = 0
43 TYPESHIFT = NRSHIFT + NRBITS
44 SIZESHIFT = TYPESHIFT + TYPEBITS
45 DIRSHIFT = SIZESHIFT + SIZEBITS
46 WRITE = 0x1
47 READ = 0x2
48
49 def IOC(direction, _type, nr, size):
50 return (direction << DIRSHIFT) | (_type << TYPESHIFT) | (nr << NRSHIFT) | (size << SIZESHIFT)
51
52 def IOWR(_type, nr, size):
53 return IOC(READ|WRITE, _type, nr, size)
54
55 BINDER_CTL_ADD = IOWR(98, 1, 264)
56 binderctrlfd = open('/dev/binderfs/binder-control','rb')
57
58 for node in binder_dev_nodes:
59 node_struct = struct.pack(
60 '256sII', bytes(node, 'utf-8'), 0, 0)
61 fcntl.ioctl(binderctrlfd.fileno(), BINDER_CTL_ADD, node_struct)
62
63 def probeBinderDriver(args):
64 binder_dev_nodes = []
65 has_binder = False
66 has_vndbinder = False
67 has_hwbinder = False
68 for node in BINDER_DRIVERS:
69 if os.path.exists("/dev/" + node):
70 has_binder = True
71 if not has_binder:
72 binder_dev_nodes.append(BINDER_DRIVERS[0])
73 for node in VNDBINDER_DRIVERS:
74 if os.path.exists("/dev/" + node):
75 has_vndbinder = True
76 if not has_vndbinder:
77 binder_dev_nodes.append(VNDBINDER_DRIVERS[0])
78 for node in HWBINDER_DRIVERS:
79 if os.path.exists("/dev/" + node):
80 has_hwbinder = True
81 if not has_hwbinder:
82 binder_dev_nodes.append(HWBINDER_DRIVERS[0])
83
84 if len(binder_dev_nodes) > 0:
85 if not isBinderfsLoaded(args):
86 command = ["modprobe", "binder_linux"]
87 output = tools.helpers.run.user(args, command, check=False, output_return=True)
88 if output:
89 logging.error("Failed to load binder driver")
90 logging.error(output.strip())
91
92 if isBinderfsLoaded(args):
93 command = ["mkdir", "-p", "/dev/binderfs"]
94 tools.helpers.run.user(args, command, check=False)
95 command = ["mount", "-t", "binder", "binder", "/dev/binderfs"]
96 tools.helpers.run.user(args, command, check=False)
97 allocBinderNodes(args, binder_dev_nodes)
98 command = ["ln", "-s"]
99 command.extend(glob.glob("/dev/binderfs/*"))
100 command.append("/dev/")
101 tools.helpers.run.user(args, command, check=False)
102
103 return 0
104
105 def probeAshmemDriver(args):
106 if not os.path.exists("/dev/ashmem"):
107 command = ["modprobe", "ashmem_linux"]
108 output = tools.helpers.run.user(args, command, check=False, output_return=True)
109 if output:
110 logging.error("Failed to load ashmem driver")
111 logging.error(output.strip())
112
113 if not os.path.exists("/dev/ashmem"):
114 return -1
115
116 return 0
117
118 def setupBinderNodes(args):
119 has_binder = False
120 has_vndbinder = False
121 has_hwbinder = False
122 if args.vendor_type == "MAINLINE":
123 probeBinderDriver(args)
124 for node in BINDER_DRIVERS:
125 if os.path.exists("/dev/" + node):
126 has_binder = True
127 args.BINDER_DRIVER = node
128 if not has_binder:
129 raise OSError('Binder node "binder" for waydroid not found')
130
131 for node in VNDBINDER_DRIVERS:
132 if os.path.exists("/dev/" + node):
133 has_vndbinder = True
134 args.VNDBINDER_DRIVER = node
135 if not has_vndbinder:
136 raise OSError('Binder node "vndbinder" for waydroid not found')
137
138 for node in HWBINDER_DRIVERS:
139 if os.path.exists("/dev/" + node):
140 has_hwbinder = True
141 args.HWBINDER_DRIVER = node
142 if not has_hwbinder:
143 raise OSError('Binder node "hwbinder" for waydroid not found')
144 else:
145 for node in BINDER_DRIVERS[:-1]:
146 if os.path.exists("/dev/" + node):
147 has_binder = True
148 args.BINDER_DRIVER = node
149 if not has_binder:
150 raise OSError('Binder node "binder" for waydroid not found')
151
152 for node in VNDBINDER_DRIVERS[:-1]:
153 if os.path.exists("/dev/" + node):
154 has_vndbinder = True
155 args.VNDBINDER_DRIVER = node
156 if not has_vndbinder:
157 raise OSError('Binder node "vndbinder" for waydroid not found')
158
159 for node in HWBINDER_DRIVERS[:-1]:
160 if os.path.exists("/dev/" + node):
161 has_hwbinder = True
162 args.HWBINDER_DRIVER = node
163 if not has_hwbinder:
164 raise OSError('Binder node "hwbinder" for waydroid not found')
165
166 def loadBinderNodes(args):
167 cfg = tools.config.load(args)
168 args.BINDER_DRIVER = cfg["waydroid"]["binder"]
169 args.VNDBINDER_DRIVER = cfg["waydroid"]["vndbinder"]
170 args.HWBINDER_DRIVER = cfg["waydroid"]["hwbinder"]