couriersud / msigd

MSI Gaming Device control application
GNU General Public License v2.0
53 stars 18 forks source link

Unknown monitor MPG27CQ - Steel series RGB support #16

Open terencode opened 4 years ago

terencode commented 4 years ago
DEBUG: Initializing HID lib
Unexpected id combination <001><V18>
Detected an unknown monitor. Please report the output of
'msigd --info --debug --query' as an issue and also provide
the ID (MAG...) of your monitor. Thank you!
Vendor Id:      0x1462
Product Id:     0x3fa4
Product:        MSI Gaming Controller
Serial:         A02017120100
Monitor Series: MAG32 Series
s140:           <001>
s150:           <V18>
DEBUG: Special 01 b0: 01 5a 67 00 00 00 00 00 00 00 00 00 00 00 00 00
DEBUG: Special 01 b4: 01 5a 02 ea 06 3c 00 00 00 00 00 00 00 00 00 00
DEBUG: Error 0 reading from HID device
DEBUG: Error receiving 01 d0 62 30 30 31 30 30 30 30 30 0d: 0
macro_key : '000'
mode : '000'
serial : 'FA3T038420211'
frequency : '144'
game_mode : '000'
unknown210 : '009'
response_time : '000'
enable_dynamic : '000'
hdcr : '000'
refresh_display : '000'
refresh_position : '001'
alarm_clock : '000'
alarm_clock_index : '000'
alarm_clock_time : '00l'
alarm_position : '000'
screen_assistance : '000'
unknown280 : '001'
zero_latency : '001'
screen_size : '003'
msigd: Error querying device on night_vision - got '56006'
Try 'msigd --help' for more information.
pro_mode : '000'
eye_saver : '000'
image_enhancement : '001'
brightness : '066'
contrast : '060'
sharpness : '001'
color_preset : '001'
color_red : '100'
color_green : '100'
color_blue : '100'
color_rgb : '0x949494'
unknown435 : '000'
input : '002'
pip : '000'
pip_input : '002'
pbp_input : '002'
pip_size : '002'
pip_position : '000'
osd_language : '001'
osd_transparency : '000'
osd_timeout : '020'
sound_enable : '000'
rgb_led : '000'
navi_up : '002'
navi_down : '001'
navi_left : '007'
navi_right : '005'

PS: Thank you very much for your work :+1:

couriersud commented 4 years ago

Pushed commit to support the monitor. Can you please rerun msigd --info --debug --query to post output here?

terencode commented 4 years ago
DEBUG: Initializing HID lib
Vendor Id:      0x1462
Product Id:     0x3fa4
Product:        MSI Gaming Controller
Serial:         A02017120100
Monitor Series: MPG271 Series
s140:           <001>
s150:           <V18>
DEBUG: Special 01 b0: 01 5a 67 00 00 00 00 00 00 00 00 00 00 00 00 00
DEBUG: Special 01 b4: 01 5a 02 ea 06 3c 00 00 00 00 00 00 00 00 00 00
DEBUG: Error 0 reading from HID device
DEBUG: Error receiving 01 d0 62 30 30 31 30 30 30 30 30 0d: 0
macro_key : '000'
serial : 'FA3T038420211'
frequency : '144'
game_mode : '000'
black_tuner : '009'
response_time : '000'
enable_dynamic : '000'
hdcr : '000'
refresh_display : '000'
refresh_position : '001'
alarm_clock : '000'
alarm_clock_index : '000'
alarm_clock_time : '00l'
alarm_position : '000'
screen_assistance : '000'
free_sync : '001'
zero_latency : '001'
screen_size : '003'
pro_mode : '000'
eye_saver : '000'
image_enhancement : '001'
brightness : '066'
contrast : '060'
sharpness : '001'
color_preset : '001'
color_red : '100'
color_green : '100'
color_blue : '100'
color_rgb : '0x949494'
unknown435 : '000'
input : '002'
pip : '000'
pip_input : '002'
pbp_input : '002'
pip_size : '002'
pip_position : '000'
osd_language : '001'
osd_transparency : '000'
osd_timeout : '020'
sound_enable : '000'
rgb_led : '000'
navi_up : '002'
navi_down : '001'
navi_left : '007'
navi_right : '005'
terencode commented 4 years ago

By the way I tried setting the mystic lights I have but I get this:

./msigd --mystic 0xFF0000
ioctl (SFEATURE): Connection timed out
couriersud commented 4 years ago

Monitor Series: MPG271 Series Ok, one typo to fix ... MPG271 -> MPG27

couriersud commented 4 years ago

By the way I tried setting the mystic lights I have but I get this:

./msigd --mystic 0xFF0000
ioctl (SFEATURE): Connection timed out

This will be tricky to fix. The Win10 MSI app shows 9 leds which can be controlled. How many are shown for the MPG27? Alternatively: If you have a virtual Win10 machine and know how to use wireshark: Install MSI software in virtual machine, connect MSI usb interface to virtual machine and log usb traffic. Than change mystic leds a number of times. Stop logging and provide log.

terencode commented 4 years ago

You mean the MSI Gaming OSD 2.0 software?

I do have Win 10 VM with wireshark so I'll prepare the log.

couriersud commented 4 years ago

You mean the MSI Gaming OSD 2.0 software? Yes I do have Win 10 VM with wireshark so I'll prepare the log. I have used wireshark on linux to track the VM usb traffic. But may work out of Win10 VM as well.

terencode commented 4 years ago

I have used wireshark on linux to track the VM usb traffic. But may work out of Win10 VM as well.

Yes I tried it before and it works correctly.

About the MSI Gaming OSD 2.0, the thing is: I do not see any LED setting in this program.

It uses "Steelserie GameSense".

couriersud commented 4 years ago

image

This is the mystic light app which is launched out from the MSI app. GameSense is not available. We may try a GameSense log, but I don't make any promises to make it work. In the best case it's the same protocal, in the worst case it is completely different.

terencode commented 4 years ago

I spent two hours trying to figure out why I couldn't control the lights from the VM and then from Windows... It's so dumb... It's because LEDs were disabled from the OSD.

On this monitor there are two usb devices used:

Disabling LEDs from the OSD was making the "SteelSerie MSC" undetectable...

So now that I figured this out, I can control the LEDs from the Windows VM, but only from SteelSeries Engine 3

I'll retry on real Windows to see if the same happens.

In the meanwhile here is how it looks like :

image image

And here is the capture log changing a led color a few times:

gamesense.zip

terencode commented 4 years ago

I was able to use mystic lights on non-VM Windows 10. Here is the capture file: mystic.zip

couriersud commented 4 years ago

I had a look at your capture files. Thanks a lot for the effort!

Unfortunately the gamesense protocol seems to be completely different from the mystic rgb protocol.

I found the following documentation here on github: https://github.com/SteelSeries/gamesense-sdk

and some client example:

https://github.com/arxae/Gamesense

All of this seems to rely on some server (closed source) running on windows accepting json requests. The underlying hid/usb protocol is not documented.

gamesense.pcap seems incomplete. Couldn't identify the device. From mystic.pcap it looks like the gamesense device is 1.11 (steel series) and leds are controlled by report request control messages.

But without a real device it is not possible for me to develop a driver. If I would have a device, the route I would take would be to identify messages which set all leds to white, than black, red, blue, green. These 5 colors should be enough to decode the data format - or at least have a start. Control messages are

control_msg_write(0x21, 0x09, 0x300, 0, &data, static_cast<int>(sizeof(led_data)), 1000)

That's basically (0x300 instead of 0x371) the same call as the mystic light call.

couriersud commented 4 years ago

Thismost recent commit has debug support for the steel series interface residing on a separatate usb manufacturer id and device id combo.

./msigd --test_steel should switch 8 LEDs to red. Can you please try to run this and post the output here?

In addition, the ouput of sudo lsusb -v for the steel series usb device would be helpful.

Thank you!

The interface for steel series mice is pretty well documented in this project:

https://github.com/flozz/rivalcfg/tree/master/rivalcfg

terencode commented 4 years ago

Hey that's really cool!

I was about to try to either try to generate a new pcap when using steelserie software or start to document myself on how to reverse engineer this properly given your first clues. Let me know if I should still try to do one of the above.

Here is the output of ./msigd --test_steel :

./msigd --test_steel
DEBUG: Initializing HID lib

I didn't notice anything different looking at the leds.

Here is the the lsusb output:

Bus 001 Device 011: ID 1038:1126 SteelSeries ApS 
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               2.00
  bDeviceClass            0 
  bDeviceSubClass         0 
  bDeviceProtocol         0 
  bMaxPacketSize0        64
  idVendor           0x1038 SteelSeries ApS
  idProduct          0x1126 
  bcdDevice            2.26
  iManufacturer           1 SteelSeries
  iProduct                2 SteelSeries MLC
  iSerial                 0 
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength       0x003b
    bNumInterfaces          2
    bConfigurationValue     1
    iConfiguration          0 
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              300mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      37
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x81  EP 1 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0040  1x 64 bytes
        bInterval               1
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        1
      bAlternateSetting       0
      bNumEndpoints           1
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 
      bInterfaceProtocol      0 
      iInterface              0 
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.11
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength      25
         Report Descriptors: 
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0004  1x 4 bytes
        bInterval               1
can't get device qualifier: Resource temporarily unavailable
can't get debug descriptor: Resource temporarily unavailable
Device Status:     0x0000
  (Bus Powered)
couriersud commented 4 years ago

The test output tells me that the steelseries device is accepting the message. Good. Now the following would be helpful:

Apart from the "0e" messages I have seen "0d" and "0b" messages as well. With the approach above we should be able to identify the color information fields and the start-up sequence.

terencode commented 4 years ago

Done, followed everything correctly I think but note I did it inside a VM.

steelseries.zip

couriersud commented 4 years ago

Just committed extended test code. ./msigd --test_steel should now circle through white, red, green, blue (1 second delay). Please provide output. If this doesn't work, a pcap would be helpful.

terencode commented 4 years ago

Nice! It's working as you said.

Same output as before.

couriersud commented 4 years ago

Just committed another text extension: Using --test_steel after circling through red, green, blue switch front leds to yellow one after the other. There should be 40 leds on the front in 5 groups. And 4x10 leds on the back left and 10,9,4 leds on the back right.

Can you please confirm the front leds turn yellow and the number of leds?

terencode commented 4 years ago

I confirm your numbers and that the front leds turn yellow progressively (although not smoothly): https://imgur.com/ub8y5Yh

couriersud commented 4 years ago

That's seems to be an issue with the firmware. I'll provide a different approach tomorrow. It looks like that every "persist" seems to cause some flicker. This is also visible on the transition from white to red, green and blue. What you may try is to comment out the calls to steel.perist() and check if the color switching still works. That would be very helpful. Does the same flicker happen if you use the native app? But at least we now have a starting point and can set individual leds as well as group of leds.

terencode commented 4 years ago

I commented all the steel.persist() calls but then the leds were not changing. Feels like steel.persist() is a bit like a buffer flush.

With the native app, there is a "live preview mode". When enabled, it will not flicker when not changing all leds. I recorded a new pcap with the live preview mode enabled: steelserie-live.zip

What I did was start the software (live preview was already enabled) then change some groups of front leds to red two times. After that I toggled live preview off and then on and finally saved all the changes. Hope that helps!

Thank you for all your investment so far :)

couriersud commented 4 years ago

Please try --test_steel with latest code again. This should be flicker-free now.

terencode commented 4 years ago

Indeed: https://imgur.com/y7MInx8 although I see some small flickering as if one led randomly turned off and on again in the group of blue leds.

couriersud commented 4 years ago

It's either the first or one in the middle of a group. This seems really firmware related.

terencode commented 4 years ago

Yep it's firmware related as the same happens with the original software. It's just a very minor annoyance anyway.

terencode commented 4 years ago

I recorded a new pcap: steelserie_adv.zip I set the 5 front groups to the effect "color shift" which is highly configurable but here I just used the default settings. After enabling it, I toggled on "Wave mode". Finally I played with the "Global Illumination" slider which just sets the brightness of the LEDs. Note that I didn't hit the "save" button, everything was done using live preview mode.

image

There is also another mode called "MultiColor Breath" but I didn't use it in this pcap. Let me know if you want me to record another one with something done differently.

terencode commented 4 years ago

Also, because we are doing some experiments with this, maybe it would have been better to switch to a new branch as not to "pollute" the master branch with test commits.

couriersud commented 4 years ago

I was able to identify global illumination now. For the other settings. When you enable colorshift, you have to change the colorshift colors and speed as well. The software only sends changes to the monitor. So you need to change colors and speed twice so it can be identified. Can you also please post a screenshot of the back view - I need this to confirm there are two groups at the back.

terencode commented 4 years ago

Here is what it looks like in the software: image And IRL: image

New pcap: colorshift.zip

  1. Enabled ColorShift
  2. Set speed Max then Speed min
  3. Disabled then enabled wave mode
  4. Set wave mode speed to min and then max
terencode commented 4 years ago

Forgot about the colors.

Here is one where I just switch between 3 different color presets: colorshift-color.zip

The presets for reference: image image

image

couriersud commented 4 years ago

It looks like wave mode was enabled during the color changes. To keep things simple, please run this without wave mode. Decoding the presets from the pcap I find extremely difficult. It would help if instead of using presets you would actually change the colors. In addition I also need information on whether the changes are applied to individual leds, groups or zones. The screenshot you provided on the back shows the zones. At the time being, a screenshot showing the groups would be more helpful.

couriersud commented 4 years ago

The test now also tests global illuminace and enabling/disabling colorshift mode.

terencode commented 4 years ago

Here is a pcap where I enable colorshift only to the first group of front led with a video showing how I tweaked it: steelserie-colorshift.zip

https://imgur.com/dVhbmXe

The screenshot you provided on the back shows the zones. At the time being, a screenshot showing the groups would be more helpful.

here is the screenshot showing the zones:

image

The test now also tests global illuminace and enabling/disabling colorshift mode.

I ran the test but it seems to loop indefinitely on the global illumination: I see the the front leds fade in to yellow again and again.

Let me know if you need anything else.

couriersud commented 4 years ago

I fixed the endless loop. Would be great if you could test it. After the fading, it will turn on colorshift for two seconds. Thanks for providing the screenshot. This confirms seven groups. Should help with the type-b packets.

couriersud commented 4 years ago

Can you please do the above for group 4 as well?

terencode commented 4 years ago

I fixed the endless loop. Would be great if you could test it. After the fading, it will turn on colorshift for two seconds.

I get passed the fading but the colorshift is not doing anything.

Can you please do the above for group 4 as well?

I'm not sure what you mean, a screenshot? there is one above: https://github.com/couriersud/msigd/issues/16#issuecomment-645938812

couriersud commented 4 years ago

In https://github.com/couriersud/msigd/issues/16#issuecomment-646275221 you used the first group:

Here is a pcap where I enable colorshift only to the first group of front led with a video showing how I tweaked it:

I am asking for the same (without video) done for group 4. Internally group 1 is 0 and there are tons of zeros in the packet so I can't identify the group.

terencode commented 4 years ago

Ah got it, here you go: colorshift_g4.zip

On this one, I assigned colorshift to group 4 with only 1 color (black) and then I added at the beginning another color (white). image

Maybe there are lots of 0s because you can add up to 16 different color shifts? image

couriersud commented 4 years ago

Just so I under stand it. You can assign the gray level colorshift to group 4. Than you assign a red color shift to group 1. Group 4 than cycles through grey and Group 1 through red?

couriersud commented 4 years ago

Ok, committed another try. After global illumination test, colorshift should be enable for 5 seconds (default colors or last used, or random) After those 5 seconds, some purple/red colorshift scheme is sent and should be used. After that, the "disabling ..." message is a bit misleading here, it should switch to another color shift scheme.

terencode commented 4 years ago

Just so I under stand it. You can assign the gray level colorshift to group 4. Than you assign a red color shift to group 1. Group 4 than cycles through grey and Group 1 through red?

I think you are correct yes. I think what it is is you create a gradient with those little pickers like one is black and one is white and it will fill the space in-between with a transition from the first color to the second one. It seems you can assign different effect to different groups / zone .

Here is the official explanation: image

Hopefully this is clear enough but as always let me know if you need more precision.

Ok, committed another try. After global illumination test, colorshift should be enable for 5 seconds (default colors or last used, or random) After those 5 seconds, some purple/red colorshift scheme is sent and should be used. After that, the "disabling ..." message is a bit misleading here, it should switch to another color shift scheme.

Seems to work correctly. Here is how it looks: https://imgur.com/a/jwJW3Kj

couriersud commented 4 years ago

Cool. Basically from the usb api it looks like one can create 19 color shift schemes. These schemes can be attached to individual leds. The 0b packet sets one of the 19 color shift schemes. I am not yet sure I understood the full packet structure but I have enough information to add more command line options.

couriersud commented 4 years ago

Commit message follows. Testing much appreciated :-)

msigd now accepts command line like

./msigd --steel --color 0-102:FFFFFF --flush --delay 2000 --illum 128 --flush

This should set the color of all leds to white and dim to a global illumination setting of 128. --color 8-15:FF0000 should set all 8 leds in group 2 to red.

The old steel test can still be called using

./msigd --steel --test

Effects are still missing, this needs some more analysis.

terencode commented 4 years ago

Very nice! What links to 8-15 to group2 ? 15 = group 2 and 8 = all leds?

EDIT: Ah it might be the range of leds to update.

terencode commented 4 years ago

Is it important to use --delay ? Also I figured that you can set a bunch of different things without --flush and then use it at the end so that it shows all the combined settings at once. This is how it's supposed to work right?

terencode commented 4 years ago

I tested different combinations for 10mn and it seems to work as expected.

couriersud commented 4 years ago

What links to 8-15 to group2 ? 15 = group 2 and 8 = all leds?

Right, it's a range. Single led like 99:FFFF00 should work as well: 0-7 : Group1 ... 32-39: Group5 40-62: Group6 (23, Back) 63-102: Group7 (40, Back)

couriersud commented 4 years ago

Is it important to use --delay ?

No, it's a feature. For the monitor interface minimum delays are needed. For the steel interface this doesn't seem to be the case.

Also I figured that you can set a bunch of different things without --flush and then use it at the end so that it shows all the combined settings at once. This is how it's supposed to work right?

Yes. You may also use --persist to store the settings permanently.

terencode commented 4 years ago

Cool. Let me know if you want me to test anything else or record a new pcap of something :)