realtek: add feed

This adds the feed holding the realtek target specific packages.

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2020-10-29 08:49:15 +01:00
parent 764aedd53e
commit cded4ebf9a
5 changed files with 400 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=rtl83xx-poe
PKG_RELEASE:=2
PKG_LICENSE:=GPL-2.0+
include $(INCLUDE_DIR)/package.mk
define Package/rtl83xx-poe
SECTION:=utils
CATEGORY:=Utilities
DEPENDS:=+libubox-lua +libubus-lua +libuci-lua +lua-rs232
TITLE:=PoE daemon for realtek switches
endef
define Package/rtl83xx-poe/description
This package contains an utility to allow triggering the PoE state of realtek switch ports.
endef
define Build/Compile
endef
define Package/rtl83xx-poe/install
$(CP) ./files/* $(1)/
endef
$(eval $(call BuildPackage,rtl83xx-poe))

View File

@@ -0,0 +1,316 @@
#!/usr/bin/lua
local rs = require "luars232"
port_name = "/dev/ttyS1"
out = io.stderr
nseq = 0
budget = 65.0
port_power = {0, 0, 0, 0, 0, 0, 0, 0 }
if arg[1] ~= nil then
budget = tonumber(arg[1])
end
for i = 1, 8 do
port_power[i] = arg[i + 1]
end
function initSerial(p)
local e, p = rs.open(p)
if e ~= rs.RS232_ERR_NOERROR then
-- handle error
out:write(string.format("can't open serial port '%s', error: '%s'\n",
port_name, rs.error_tostring(e)))
return
end
assert(p:set_baud_rate(rs.RS232_BAUD_19200) == rs.RS232_ERR_NOERROR)
assert(p:set_data_bits(rs.RS232_DATA_8) == rs.RS232_ERR_NOERROR)
assert(p:set_parity(rs.RS232_PARITY_NONE) == rs.RS232_ERR_NOERROR)
assert(p:set_stop_bits(rs.RS232_STOP_1) == rs.RS232_ERR_NOERROR)
assert(p:set_flow_control(rs.RS232_FLOW_OFF) == rs.RS232_ERR_NOERROR)
out:write(string.format("OK, port open with values '%s'\n", tostring(p)))
return p
end
function receive(pCon)
local reply = {}
local retries = 0
while table.getn(reply) < 12 and retries < 4 do
-- Read up to 12 byte response, timeout 400ms
err, data_read, size = pCon:read(12, 400)
assert(err == rs.RS232_ERR_NOERROR)
-- io.write(string.format("-> [%2d]:", string.len(data_read)))
for i = 1, string.len(data_read) do
table.insert(reply, string.byte(string.sub(data_read, i, i)))
-- io.write(string.format(" %02x", reply[i]))
end
-- io.write("\n")
retries = retries + 1
end
if table.getn(reply) ~= 12 then
print ("Unexpected length!")
return(nil)
end
local sum = 0
for i = 1, 11 do
sum = sum + reply[i]
end
if sum % 256 ~= reply[12] then
print ("Checksum error!")
return(nil)
end
return(reply)
end
function sendCommand(pCon, cmd)
nseq = nseq + 1
cmd[2] = nseq % 256
while table.getn(cmd) < 11 do
table.insert(cmd, 0xff)
end
local c_string = ""
local sum = 0
-- io.write("send ")
for i = 1, 11 do
sum = sum + cmd[i]
-- io.write(string.format(" %02x", cmd[i]))
c_string = c_string .. string.char(cmd[i])
end
-- io.write(string.format(" %02x\n", sum % 256))
c_string = c_string .. string.char(sum % 256)
err, len_written = pCon:write(c_string)
assert(err == rs.RS232_ERR_NOERROR)
local reply = receive(pCon)
if reply then
-- io.write("recv ")
-- dumpReply(reply)
if (reply[1] == cmd[1] and reply[2] == cmd[2]) then
return(reply)
else
if reply[1] == 0xfd then
print ("An incomplete request was received!")
elseif reply[1] == 0xfe then
print ("Request frame checksum was incorrect!")
elseif reply[1] == 0xff then
print ("Controller was not ready to respond !")
else
print ("Sequence number mismatch!")
end
end
else
print ("Missing reply!")
end
return(nil)
end
function dumpReply(reply)
for i,v in ipairs(reply) do
io.write(string.format(" %02x", v))
end
io.write("\n");
end
function getStatus(pCon)
local cmd = {0x20, 0x01}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
-- returns status, PoEExtVersion, PoEVersion, state2
return({reply[5], reply[6], reply[7], reply[10]})
end
function disablePort(pCon, port)
local cmd = {0x00, port, port, 0x00}
-- disable command is always sent twice
sendCommand(pCon, cmd)
sendCommand(pCon, cmd)
end
function enablePort(pCon, port)
local cmd = {0x00, port, port, 0x01}
sendCommand(pCon, cmd)
end
function setPortRelPrio(pCon, port, prio)
local cmd = {0x1d, 0x00, port, prio}
sendCommand(pCon, cmd)
end
function setGlobalPowerBudget(pCon, maxPower, guard)
-- maxPower and guard Watts
local cmd = {0x18, 0x01, 0x00}
table.insert(cmd, math.floor(maxPower * 10 / 256))
table.insert(cmd, math.floor(maxPower * 10) % 256)
table.insert(cmd, math.floor(guard * 10 / 256))
table.insert(cmd, math.floor(guard * 10) % 256)
sendCommand(pCon, cmd)
end
function setPowerLowAction(pCon, disableNext)
local cmd = {0x17, 0x00}
if disableNext then
table.insert(cmd, 0x04)
else
table.insert(cmd, 0x02)
end
sendCommand(pCon, cmd)
end
function getPowerStat(pCon)
local cmd = {0x23, 0x01}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
local watts = (reply[3] * 256 + reply[4]) / 10.0
return watts
end
function getPortPower(pCon, port)
local cmd = {0x30, 0x01, port}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
local watts = (reply[10] * 256 + reply[11]) / 10.0
local mamps = reply[6] * 256 + reply[7]
return({watts, mamps})
end
function getPortOverview(pCon)
local cmd = {0x2a, 0x01, 0x00}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
local s = { }
for i = 4, 11 do
if reply[i] == 0x10 then
s[i-3] = "off"
elseif reply[i] == 0x11 then
s[i-3] = "enabled"
elseif reply[i] > 0x11 then
s[i-3] = "active"
else
s[i-3] = "unknown"
end
end
return(s)
end
-- Priority for power: 3: High, 2: Normal, 1: Low?
function setPortPriority(pCon, port, prio)
local cmd = {0x1a, port, port, prio}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
return(unpack(reply, 4, 11))
end
function getPortPowerLimits(pCon, port)
local cmd = {0x26, 0x01, port}
local reply = sendCommand(pCon, cmd)
if not reply then return(nil) end
return(reply)
end
function startupPoE(pCon)
local reply = nil
reply = getStatus(pCon)
setGlobalPowerBudget(pCon, 0, 0)
setPowerLowAction(pCon, nil)
-- do something unknown
sendCommand(pCon, {0x06, 0x00, 0x01})
for i = 0, 7 do
if port_power[i + 1] ~= "1" then
disablePort(pCon, i)
end
end
-- do something unknown
sendCommand(pCon, {0x02, 0x00, 0x01})
for i = 0, 7 do
if port_power[i + 1] ~= "1" then
disablePort(pCon, i)
end
end
-- do something unknown
sendCommand(pCon, {0x02, 0x00, 0x01})
-- use monitor command 25
sendCommand(pCon, {0x25, 0x01})
setGlobalPowerBudget(pCon, 65.0, 7.0)
getPowerStat(pCon)
-- -> 23 01 00 00 02 44 00 02 ff ff 00 6a
-- Set 4 unknown port properties:
for i = 0, 7 do
sendCommand(pCon, {0x11, i, i, 0x01})
sendCommand(pCon, {0x13, i, i, 0x02})
sendCommand(pCon, {0x15, i, i, 0x01})
sendCommand(pCon, {0x10, i, i, 0x03})
end
for i = 0, 7 do
if port_power[i + 1] == "1" then
enablePort(pCon, i)
end
end
end
local p = initSerial(port_name)
startupPoE(p)
require "ubus"
require "uloop"
uloop.init()
local conn = ubus.connect()
if not conn then
error("Failed to connect to ubus")
end
local my_method = {
poe = {
info = {
function(req, msg)
local reply = {}
reply.power_consumption = tostring(getPowerStat(p)).."W"
reply.power_budget = tostring(budget).."W"
reply.ports = {}
local s = getPortOverview(p)
for i = 1, 8 do
if s[i] == "active" then
local r = getPortPower(p, i - 1)
reply.ports[i] = tostring(r[1]).."W"
else
reply.ports[i] = s[i]
end
end
conn:reply(req, reply);
end, {}
},
port = {
function(req, msg)
local reply = {}
if msg.port < 1 or msg.port > 8 then
conn:reply(req, false);
return -1
end
if msg.enable == true then
enablePort(p, msg.port - 1)
else
disablePort(p, msg.port - 1)
end
conn:reply(req, reply);
end, {port = ubus.INT32, enable = ubus.BOOLEAN }
},
},
}
conn:add(my_method)
uloop.run()

View File

@@ -0,0 +1,10 @@
config poe poe
option budget 65
option port1 0
option port2 0
option port3 0
option port4 0
option port5 0
option port6 0
option port7 0
option port8 0

View File

@@ -0,0 +1,24 @@
#!/bin/sh /etc/rc.common
START=40
USE_PROCD=1
PROG=/bin/poe.lua
service_triggers() {
procd_add_reload_trigger ucentral
}
start_service() {
[ "$(uci get poe.poe.enable)" -eq 1 ] || return 0
local budget=$(uci get poe.poe.budget)
procd_open_instance
procd_set_param command "$PROG"
procd_append_param command ${budget:-65}
for p in `seq 1 8`; do
local pwr=$(uci get poe.poe.port$p)
procd_append_param command ${pwr:-0}
done
procd_close_instance
}

View File

@@ -0,0 +1,21 @@
#!/bin/sh
. /lib/functions.sh
board=$(board_name)
budget=0
case "$board" in
d-link,dgs-1210-10p)
budget=65
;;
netgear,gs110tpp-v1|\
zyxel,gs1900-10hp)
budget=130
;;
*)
exit 0
;;
esac
uci set poe.poe.enable=1
uci set poe.poe.budget=$budget