As usual, this document is just a draft and needs more content.
For details about HID data formats and concepts, please read details from following web page:
When working with HID, forget anything you have learned about MIDI. Unlike MIDI, HID sends data packets with size anything from 1 byte to maximum value allowed by standard (check from specs what it is), and similarly arbitrary size HID packets can be sent to devices.
In HID, each input and output packet usually contains information for multiple fields: for example, a HID keyboard sends 1 byte keycode for 6 different pressed keys simultaneously with three byte header with values 0x1,0x0,0x0 in the header, so total packet size is 9 bytes. Similarly, on a typical HID controller, you will receive a packet with multiple control values and send data for multiple output controls (LEDs, text fields etc) in one larger packet.
The HID standard has concept of HID usage page, which contains descriptions of each byte in input and output packets. Unfortunately it's not mandatory to provide these packets, and typical DJ controller does not provide these packets. Thus, we must parse our own HID packets in Mixxx.
Unlike MIDI data, HID can contain multiple byte values for single field: for example, most HID controllers send fader details in a 2 byte (short) numeric field, not necessarily using whole range of values. As an example, Pioneer CDJ pitch fader has value range -1000 to 1000, expressed with two bytes. Another example of complex HID packet fields is the output packet for Pioneer CDJ devices, which sends the waveform display in one packet to the device: the packet size is hundreds of bytes.
|b / B||unsigned/signed byte|
|h / H||unsigned/signed two byte value (short)|
|i / I||unsigned/signed four byte value (int)|
The bit mask fields are implemented as normal numeric value field, which has type bitvector and which has value of internal class HIDBitVector. Any bit mask size from 1 to number of bytes in the field is supported, but usually you want to address one bit for input button toggles.
For HID packet output, I could not bother writing any other types of output fields than bit masked bits in one byte size packets and sending of one byte numeric values, signed or unsigned: main reason I did not implement other types of fields yet is that I don't have any devices which need this. It is easy to add other packing formats, when required. Longer fields than one byte for output need to be constructed by script writer for now.
Each HID packet has following attributes:
Internally, each packet registers the packet fields following Mixxx naming conventions, i.e. each field must have a group and name. The group and name don't need to be valid Mixxx controls, but if the group is valid Mixxx control group, we try to automate mapping the field to Mixxx controls.
Since HID controller packet fields can be larger than one byte, I thought it good idea to implement field description based on following details:
Note: scaling functions and automated field group resolutio are NOT done for fields which have a registered callback function. The callback function is expected to do required field name resolution and scale values itself.
In almost every case, a HID controller sends data values with input fields which are not directly suitable for Mixxx control values. To solve this issue, HIDController contains function to scale the input value to suitable range automatically before calling any field processing functions. Scalers can be registered with HIDController.registerScalingFunction(group,name,callback) in HIDController.
HIDPacket object wraps all details of reading HID input packets and sending HID output packets to devices. HIDPackets are expected to be defined by the HID description writers only, people using the HID device description only need to read the assigned field names. HIDPacket packets have some common functions to use:
Note that all field types, the internal structure is similar. In case of bitmasked fields, the field type is set to bitvector and the bit values are stored to HIDBitVector stored in field value. Similarly a LED has type led and some extra attributes for blinking etc.
It also defines multiple documented attributes, which for example allow implementing scratching just by adding special field names 'jog_touch' and 'jog' to the HID fields, and adjusting the attribute values for scratching to get correct performance.
Following functions need to be implemented in end user classes. This is due to issues with Mixxx QtScript calls and namespaces, where this.functionName does not work correctly. Same rules as for MIDI scripts and HID scripts without HIDController objects apply.
See below examples for common usage of these functions.
There are multiple very simple mappings in Mixxx 1.11 tree, which can be studied for the expected ways of using the common hid packet parser code. The simple mappings are in: