Traktor Kontrol S4 MK3


I’ve just had a bit of spare time this weekend and wanted to have a look if I can wrap my head around a mapping for the above. I’m not sure if anything will ever come from this with time being an issue all the time … but I’d like to ask a question.

I’ve had a look at the HID packets from the controller. Now what I see it constantly spams 60 bytes wide packets which contain some ongoing changes (tick values? not sure at this point) as well as most of the slider/knob values.

If I press a button, I get a 23 bytes packet containing buttons and the open knobs (move, loop, browse). So far, so good, looks like some effort but in general doable.

When I use the sliders and closed knobs though, I think I get a 60 bytes packet (like the one that is constantly sent by the controller) plus a 15 bytes packet. The 15 bytes packet contains: the Mixer knobs of the FX section in the middle and the top right FX knobs. Now here’s the thing that confused me: the state of the leftmost mixer FX knob is split across the two packets. First byte is at the end of the 60 bytes packet, and the second byte at the beginning of the 15 byte packet.

I’ve tried to find an example but was not sure what to look for. Any hints how this could be handled?

Thanks in advance.

I have had this controller sitting on my desk waiting to be reverse engineered for some months now. However, I got it as motivation to work on the new controller mapping system, which is a long term project. I am not going to map it with the current mapping system for a few reasons. First, the current implementation of jog wheel scratching is inadequate for motorized jog wheels. The speed of the audio would wobble with the wheel turning at a steady speed. So I don’t think we’d include a mapping for this controller in Mixxx until we solve that problem in the new mapping system. Second, the common-hid-packet-parser.js library is really messy code and if you try to make a mapping with it, the mapping code will be messy. That said, if you want to start on a mapping anyway and post it here, you’re welcome to do so.

On to your question about the split HID packets, the Kontrol S4 Mk2 has the same issue on Linux and the mapping has a workaround to concatenate the split packets together. I am not sure what the cause is. Does the shorter part of the split packet always start with the same byte? If not, it’s not a real HID packet and something weird is going on either at the OS level or in hidapi. What OS are you using?

1 Like


thanks a lot for the explanations. I’m running Debian GNU/Linux here with a custom 5.11.6 kernel. The shorter part is always the same byte so at least it’s consistent.

I’ll check the S4 Mk2 mapping regarding the concatenation and see if I can make use of that.

And if I come up with anything that’s useful in the meantime, I’ll share it.


Is the first byte of each of the split packets the same or different? If it is different, then these are likely actually different packets. Why the packets are organized that way, I don’t know.

The HID Report Descriptor of the S4 MK3 tells us that there are:

InputReport 01:

  • 136 Single Bits (Buttons)
  • 16 further Single Bits (Buttons)
  • 6 4-Bit Inputs with Range from 0…15 (most likely the infinite rotary knobs for beatjump, loopsize and track selection)

InputReport 02:

  • 7 16-Bit fields with range from 0 to 4095 (most likely the faders and pitch sliders)
  • 32 further 16-Bit fields with range from 0 to 4095 (could be Gain or EQ-Knobs)

Input report 03:

  • 3 8-Bit fields with range from 0 to 255
  • 28 8-Bit fields with range from 0 to 255
  • 28 8-Bit fields with range from 0 to 255

Input report 04:

  • 39 8-Bit fields with range from 0 to 255

Output report 48:

  • 27 8-Bit fields with range from 0 to 255 (Display?)

Output report 49:

  • 10 8-Bit fields with range from 0 to 255 (Display?)

Output report 50:

  • 40 8-Bit fields with range from 0 to 255 (Display?)

Output Report 128:

  • 94 8-Bit fields with range from 0 to 127 (Dimable LEDs?)

Output Report 129:

  • 78 8-Bit fields with range from 0 to 127 (Most likely the dimable LEDs of the VU meters)

Output Report 130:

  • 8 8-Bit fields with range from 0 to 127 (Dimable LEDs?)

Output Report 142:

  • 62 8-Bit fields with range from 0 to 255

Than there are also some FeatureReports to configure the device behaviour. This could be things like enabling MIDI mode, nominal speed of the jogs, audio output routing,calibration values. It’s likely, that these values are stored in a non-volatile memory inside the controller. Be carful here, because this could change the device behavior permanent.

If you’ve access to a Traktor Pro installation on Windows, I recommend USBlyzer to record the messages. The software can be tested for 33 days. After that you can still display you’re captured data files. Take care to captureall the special cases during this period. Especially what happens if you modify the S4 controller preferences in Traktor Pro.


Wireshark is a free program that can be used for analyzing the traffic as well.

I tried it, Wireshark doesn’t interprets the HID information. Wireshark is not suitable for this purpose.

Maybe it was me. I wasn’t able to display helpful information with Wireshark, while I achieved this with USBlyzer out of the box.
Next time I’ve to try something else, because my USBlyzer trial period is over…

OK, I must have looked wrong the first time round and I have to correct myself. When I move any of the sliders/knobs I get two packets (64/15 bytes). All of the bytes refer to something I can move so all good except for somehow joining the packets but I’ll check out the example. The bigger one is 64 bytes so that’s probably the max length.

When I press any buttons, I get a 23 bytes packet, so that’s good too.

The recurring 60 bytes packet I saw is independent, I just got visually confused.

I guess I need to get a better understanding of HID packets and what’s going on between the controller and Traktor, so that’s a good hint too, thanks for that.


The first byte is the Report ID, with this you can look up the ranges above.

1 Like

Are you able to test the controller with Mixxx on Windows? You could try this with a virtual machine. If the big packet is not split, I think we should figure out why it is being split on Linux and work upstream in hidapi to fix that bug.

Could you try building hidapi with the hidraw backend instead of the libusb backend, linking Mixxx to that, and check if the large packet is split?

yes, I should be able to try both.

I think 60bytes is correct, InputReport 03 has a size of 59 bytes, with the ReportID byte, which HIDAPI adds at the begin of the array, it’s 60 bytes.

Also the 23 byte report matchs to the size of InputReport 01

Try if you get report 02 with 79 bytes size if you turn any gain or EQ knob

OK, so the recurring message is report 3 (60 bytes), the sliders (which is split) is report 2 (64+15 bytes), and the buttons is report 1. (23 bytes)

Than the HID communication from the controller to Mixxx works as expected!

If you send OutputReports, take care that you use the exact size. If the size doesn’t match, HIDAPI doesn’t send the data to the device.
As start for the LED output, you could copy and adjustthe debugLights function from the following mapping: mixxx/Traktor-Kontrol-Z2-hid-scripts.js at b76d7b821f3b67c535e4fb2a9df3011d374af6b3 · mixxxdj/mixxx · GitHub

I don’t think so.

This still doesn’t make sense and I suspect is caused by a bug hidapi.

Try to call
in your mapping.
Inside HIDAPI, this command is implemented completly independent from the input polling.

This command is only available in Main (2.4) builds of Mixxx.

1 Like