Open rhgndf opened 1 year ago
Wow, I'm so glad my notes were good enough to help someone write a kernel driver! Also, thank you for figuring out the PLL configuration--it would be nice to be able to support fully custom resolutions, or even simply less-common aspect ratios like the 16:10 1280x800 or 1920x1200.
To answer your questions:
0x5800
indicates that the connector is HDMI, while a PID of 0x5804
indicates that it's VGA, but I only know this because I plugged in some Trigger 5 devices and noted their PIDs manually (USB32HDES, JUA350, JUA310)--I don't know the connector types for any of the other Trigger 5 PIDs because I don't own any devices that use those PIDs.0, 0, width, height
to the horizontal offset, vertical offset, width, and height of the rectangular area you want to update. See the "Horizontal pixel offset info" and "Vertical pixel offset info" fields in the bulk endpoint packet format.Thanks!
You can look at the PLL code in pllcheck.py
The mode set needs a mode number as the value, not sure when setting a custom resolution how to deal with this.
Is there a way to power on or off the whole dongle or the display? That will be useful in implementing some functions in the driver.
Seems like the the mode number doesn't matter. It is possible to output other resolutions.
This looks straightforward to implement
I reviewed some of my not-yet-published notes, and found some dumps of the result of the "Get firmware info?" request for the three Trigger 5 devices I own:
02010200000410000112000c0c1c
: JUA310, VGA02010500090510010112000e030c
: JUA350, HDMI02020200000510010112000f0318
: USB32HDES, HDMIThe first three bytes are the firmware version (I think), the last three are the firmware date (I think), and the eight bytes in-between are unknown. Some of those bits may indicate the connector type, but then again maybe none of them indicate the connector type and they're used for something else entirely. Unfortunately, I simply don't have a large enough sample size to be able to definitively isolate and identify device attributes in these bytes, assuming they have anything to do with them in the first place.
I tried to do that but all I got is a blank screen. Only when the fields are 0,0,width,height the screen starts displaying.
It's strange to me that partial updates aren't working for you. Are you clearing the image FIFO on device initialization and sending keepalive packets as needed? Are you updating the frame counter and setting all the necessary bits in the bulk data header?
Maybe you could try patching test_t5.py
using the diff below, and then compare a packet capture of it to what your kernel driver is doing? Over the past couple of days I've added support to the Wireshark plugin to dissect the Trigger 5 protocol, so if there's any big differences in how your driver is operating compared to my test code it should be easy to see them in the capture.
diff --git a/test_t5.py b/test_t5.py
index 111ba5c..e5ffd04 100755
--- a/test_t5.py
+++ b/test_t5.py
@@ -18,6 +18,7 @@
import argparse
import itertools
+import random
import struct
import time
@@ -215,8 +216,16 @@ def main():
while True:
dev.ctrl_transfer(CONTROL_OUT, 0xc8, c_x, c_y)
- payload = bytes(struct.pack('<I', (red << 16) | (green << 8) | blue)[:3] * width * height)
- header = struct.pack('<BBHHHHHIBBB', 0xfb, 0x14, (0 << 13) | (0 << 12) | counter, 0, 0, width, height, len(payload), 0x01, 0, 0)
+ rwidth = random.randrange(1, (width//4)+1, 1)
+ rheight = random.randrange(1, (height//4)+1, 1)
+ rx = random.randrange(0, width-rwidth+1, 1)
+ ry = random.randrange(0, height-rheight+1, 1)
+ #rwidth = 1920
+ #rheight = 1080
+ #rx = 0
+ #ry = 0
+ payload = bytes(struct.pack('<I', (red << 16) | (green << 8) | blue)[:3] * rwidth * rheight)
+ header = struct.pack('<BBHHHHHIBBB', 0xfb, 0x14, (0 << 13) | (0 << 12) | counter, rx, ry, rwidth, rheight, len(payload), 0x01, 0, 0)
header += bytes([checksum(header)])
bulk_data = header + payload
Is there a way to power on or off the whole dongle or the display? That will be useful in implementing some functions in the driver.
The only way I know how to power off the display is to stop outputting a video signal by stopping sending keepalive packets and then waiting for about three seconds. Or I guess you could send a "Firmware reset" command, but I haven't yet determined what the wValue
parameter controls.
Seems like the the mode number doesn't matter. It is possible to output other resolutions.
I'm glad to hear that!
I detected whether it is HDMI or VGA by checking the number of interfaces on the device. HDMI supports audio so there are additional audio interfaces.
Thanks for the advice for the partial updates, it might be that I didn't clear the image fifo.
I was hoping to support powering on or off to implement power management since the device gets quite hot after plugged in for a while.
For the PLL, it is verified that the first value 0x1 is a pre-divider. The last value can only be a power of 2.
Seems like partial update works now. Would you like to test out the driver? Wayland might work better for some reason.
What exactly is the keepalive packet? My code does not ever send the keepalive packet but the screen is still turned on after a while?
Seems like partial update works now. Would you like to test out the driver? Wayland might work better for some reason.
Sure, I can test it.
What exactly is the keepalive packet? My code does not ever send the keepalive packet but the screen is still turned on after a while?
The keepalive packet is a control request (bmRequestType: 0xc0, bRequest: 0x91, wValue: 0x0002) that needs to be sent every two seconds to keep the screen active. IIRC, if this request isn't sent, the display output will deactivate several seconds after the last display update.
Not sure why, but the screen turning off didn't happen for my device.
Thanks for your description of the protocol!
With this and analyzing my own wireshark captures I have made this: https://github.com/rhgndf/trigger5
Some questions I have: