TL;DR
- I want
realtek-poe
to work, but to do so we need an agreed-upon place for it to be developed - I don't think
realtek-poe
will make it to mainline OpenWrt, but as it stands there's no OpenWrt-based implementation that can successfully control this very commonly seen MCU+BCM59XXX-backed PoE hardware, and I thinkrealtek-poe
is useful as an open-source reference implementation for debugging.
On my GS1900-24HPv1, the issue I'm replying to was caused by MAX_PORTS
being hard-set as 8 in realtek-poe
's main.c
. After changing that (and another instance which hard-codes 8
in a for
loop in poe_reply_port_overview
), the program runs, but does not successfully initialize PoE on any ports (so far that I've tested). I think this is because of a port mapping issue which must be dealt with for these 24-port switches.
Two things in particular:
-
The
0x0a
th sent frame always receives a response0xfe
, AKA 'Request Checksum Frame was incorrect'. I've tested multiple different configurations and found that no matter what the frame is, as long as it's the0x0a
th one, it will fail. I don't believe this is true when the Frame ID wraps over to0x0a
again. -
Frames sent to manipulate configuration on port
0x0a
always fail with response0xfe
-- and frames to manipulate port0x0d
respond with information from port0x0a
. I suspect this has to do with port mapping, and that we will have to find the original firmware's port mapping and reproduce it.
I have implemented a ubus
callback to queue up one frame:
root@OpenWrt:/# ubus -v list poe
'poe' @38a3bba9
"info":{}
"reload":{}
"sendframe":{"frame":"String"}
Using (roughly) this patch:
@ -773,6 +866,47 @@ ubus_poe_info_cb(struct ubus_context *ctx, struct ubus_object *obj,
return UBUS_STATUS_OK;
}
+enum {
+ POE_SENDFRAME_STRING,
+ __POE_SENDFRAME_MAX
+};
+
+static const struct blobmsg_policy ubus_poe_sendframe_policy[__POE_SENDFRAME_MAX] = {
+ [POE_SENDFRAME_STRING] = { "frame", BLOBMSG_TYPE_STRING },
+};
+
+static int
+ubus_poe_sendframe_cb(struct ubus_context *ctx, struct ubus_object *obj,
+ struct ubus_request_data *req, const char *method,
+ struct blob_attr *msg)
+{
+ struct blob_attr *tb[__POE_SENDFRAME_MAX];
+ blobmsg_parse(ubus_poe_sendframe_policy, __POE_SENDFRAME_MAX, tb, blob_data(msg), blob_len(msg));
+
+ if (!tb[POE_SENDFRAME_STRING])
+ return UBUS_STATUS_INVALID_ARGUMENT;
+
+ char *frame = blobmsg_get_string(tb[POE_SENDFRAME_STRING]);
+
+ unsigned int frame_strlen = strlen(frame);
+ unsigned char cmd[9];
+ unsigned int cmdsize = 0;
+ unsigned char *end = cmd + sizeof(cmd);
+ unsigned int u;
+ unsigned int i = 0;
+
+ while ((cmd + cmdsize < end) && (i < frame_strlen)) {
+ if (sscanf((frame+i), "0x%2x", &u) == 1) {
+ cmd[cmdsize++] = u;
+ i += 4;
+ } else
+ i += 1;
+ }
+ return poe_cmd_queue(cmd, cmdsize);
+}
+
static int
ubus_poe_reload_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method,
@@ -787,6 +921,7 @@ ubus_poe_reload_cb(struct ubus_context *ctx, struct ubus_object *obj,
static const struct ubus_method ubus_poe_methods[] = {
UBUS_METHOD_NOARG("info", ubus_poe_info_cb),
UBUS_METHOD_NOARG("reload", ubus_poe_reload_cb),
+ UBUS_METHOD("sendframe", ubus_poe_sendframe_cb, ubus_poe_sendframe_policy),
};
This will enqueue up to 9 bytes as a frame (using the same code path as all of the frame command senders to handle frame number / checksumming); unfortunately I'm not a strong C programmer and haven't thought of a good way to retrieve the response to the frame as the frame is only enqueued and not waited on -- but I might be misunderstanding the running context of the ubus_poe_sendframe_cb
when one calls ubus call poe sendframe '{"frame": "0x01 0x01"}'
(to enable port 1, for example); it might be possible to have the method here spin / wait for the frame response, I'm just not really familiar with the ubus architecture.
To be clear, the code does work and does send the frame you ask; if running realtek-poe -d
you do see the frame being sent upon running that ubus call
.
It'd be nice to have a place to send my patches, or even an official home for realtek-poe
to be developed, but ca n'existe pas at this point. I'm happy to create a repository / specific branch for code development on Github if that would help centralize efforts, @blogic.