-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathhardware.lua
More file actions
184 lines (167 loc) · 7.97 KB
/
hardware.lua
File metadata and controls
184 lines (167 loc) · 7.97 KB
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
--- The hardware module implements functions for operating on peripherals and
-- other hardware devices.
--
-- @module system.hardware
local expect = require "expect"
local util = require "util"
local hardware = {}
--- Wraps a device into an indexable object, allowing accessing properties and
-- methods of the device by indexing the table.
-- If an object is passed, this simply re-wraps the device in a new object.
-- @tparam string device The device specifier or object to wrap
-- @treturn device The wrapped device
-- @usage Wrap a device, use a property, and call a method:
--
-- local computer = hardware.wrap("/")
-- print(computer.isOn)
-- computer.label = "My Computer"
-- computer:reboot()
function hardware.wrap(device)
expect(1, device, "string", "device", "devicetree")
if type(device) ~= "string" then device = getmetatable(device).uuid end
local info = util.syscall.devinfo(device)
if not info then return nil end
local methods, properties = util.syscall.devmethods(device), util.syscall.devproperties(device)
for _, v in ipairs(properties) do properties[v] = true end
local retval = {}
for _, v in ipairs(methods) do retval[v] = function(self, ...) return util.syscall.devcall(device, v, ...) end end
return setmetatable(retval, {
__name = "device",
uuid = info.uuid,
__index = function(self, idx)
if type(idx) == "string" and properties[idx] then return util.syscall.devcall(device, "get" .. idx:gsub("^.", string.upper)) end
end,
__newindex = function(self, idx, val)
if type(idx) == "string" and properties[idx] and self["set" .. idx:gsub("^.", string.upper)] then return util.syscall.devcall(device, "set" .. idx:gsub("^.", string.upper), val) end
end,
__tostring = function(self)
return "wrapped device: " .. (info.displayName or info.uuid)
end
})
end
--- Returns a list of wrapped devices that implement the specified type.
-- @tparam string type The type to search for
-- @treturn device... The devices found, or `nil` if none were found
-- @see wrap For wrapping a single device by path
function hardware.find(type)
expect(1, type, "string")
local retval = {}
for i, v in ipairs{util.syscall.devfind(type)} do retval[i] = hardware.wrap(v) end
return table.unpack(retval)
end
--- Returns a list of device paths that match the device specifier or object.
-- If an absolute path is specified, this returns the same path back.
-- If a device object is specified, this returns the path to the device.
-- @tparam string|device device The device specifier or object to read
-- @treturn string... The paths that match the specifier or device object.
function hardware.path(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devlookup(device)
else return util.syscall.devlookup(getmetatable(device).uuid) end
end
--- Returns whether the device implements the specified type.
-- @tparam string|device device The device specifier or object to query
-- @tparam string type The type to check for
-- @treturn boolean Whether the device implements the type
function hardware.hasType(device, typ)
expect(1, device, "string", "device", "devicetree")
expect(2, typ, "string")
local info
if type(device) == "string" then info = util.syscall.devinfo(device)
else info = util.syscall.devinfo(getmetatable(device).uuid) end
if not info then error("No such device", 2) end
return info.types[typ] ~= nil
end
--- Returns a table of information about the specified device.
-- @tparam string|device device The device specifier or object to query
-- @treturn HWInfo|nil The hardware info table, or `nil` if no device was found
function hardware.info(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devinfo(device)
else return util.syscall.devinfo(getmetatable(device).uuid) end
end
--- Returns a list of methods implemented by this device.
-- @tparam string|device device The device specifier or object to query
-- @treturn {string...} The methods available to call on this device
function hardware.methods(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devmethods(device)
else return util.syscall.devmethods(getmetatable(device).uuid) end
end
--- Returns a list of properties implemented by this device.
-- @tparam string|device device The device specifier or object to query
-- @treturn {string...} The properties available on this device
function hardware.properties(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devproperties(device)
else return util.syscall.devproperties(getmetatable(device).uuid) end
end
--- Returns a list of children of this device.
-- @tparam string|device device The device specifier or object to query
-- @treturn {string...} The names of children of the device
function hardware.children(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devchildren(device)
else return util.syscall.devchildren(getmetatable(device).uuid) end
end
--- Calls a method on a device.
-- @tparam string|device device The device specifier or object to call on
-- @tparam string method The method to call
-- @tparam any ... Any arguments to pass to the method
-- @treturn any... The return values from the method
function hardware.call(device, method, ...)
expect(1, device, "string", "device", "devicetree")
expect(2, method, "string")
if type(device) == "string" then return util.syscall.devcall(device, method, ...)
else return util.syscall.devcall(getmetatable(device).uuid, method, ...) end
end
--- Toggles whether this process should receive events from the device.
-- @tparam string|device device The device specifier or object to modify
-- @tparam[opt=true] boolean state Whether to allow events
function hardware.listen(device, state)
expect(1, device, "string", "device", "devicetree")
expect(2, state, "boolean", "nil")
if type(device) == "string" then return util.syscall.devlisten(device, state)
else return util.syscall.devlisten(getmetatable(device).uuid, state) end
end
--- Locks the device from being called on or listened to by other processes.
-- @tparam string|device device The device specifier or object to modify
-- @tparam[opt=true] boolean wait Whether to wait for the device to unlock if
-- it's currently locked by another process
-- @treturn boolean Whether the current process now owns the lock
-- @see unlock To unlock the device afterward
function hardware.lock(device, wait)
expect(1, device, "string", "device", "devicetree")
expect(2, wait, "boolean", "nil")
if type(device) == "string" then return util.syscall.devlock(device, wait)
else return util.syscall.devlock(getmetatable(device).uuid, wait) end
end
--- Unlocks the device after previously locking it.
-- @tparam string|device device The device specifier or object to modify
-- @see lock To lock the device
function hardware.unlock(device)
expect(1, device, "string", "device", "devicetree")
if type(device) == "string" then return util.syscall.devunlock(device)
else return util.syscall.devunlock(getmetatable(device).uuid) end
end
local function makeTree(path)
local info = hardware.info(path or "/")
if not info then return nil end
path = path or ""
return setmetatable({}, {
__name = "devicetree",
uuid = info.uuid,
__index = function(self, idx)
return makeTree(path .. "/" .. idx)
end,
__newindex = function() end
})
end
--- A table that allows accessing device object pointers in a tree. This is
-- simply syntax sugar for real paths.
-- @usage To access the left redstone signal
--
-- local device = hardware.wrap(hardware.tree.redstone.left)
-- print(device.input)
hardware.tree = makeTree()
return hardware