MAVLink is deployed in two major versions: MAVLink 1.0 and MAVLink 2.0.
MAVLink v1.0 was widely adopted around 2013. MAVLink 2.0 was adopted by major users early 2017, but there are still quite a few legacy peripherals in use that don't yet support it. The MAVLink 2.0 C/C++ and Python libraries are backwards compatible with MAVLink 1.0, which has tremendously simplified the transition.
Support for MAVLink 2 is indicated in the AUTOPILOT_VERSION message by the MAV_PROTOCOL_CAPABILITY_MAVLINK2 flag. This is sufficient if the communication link between autopilot and GCS is completely transparent. However, most communication links are not completely transparent as they either include routing or in case of fixed-length wireless implementations on packetization. In order to also test the link, the MAVLink 2 handshake protocol sends a MAVLink 2 frame to test the complete communication chain.
If the system supports MAVLink 2 and the handshake it will respond with PROTOCOL_VERSION encoded as MAVLink 2 packet. If it does not support MAVLink 2 it should NACK the command. The GCS should fall back to a timeout in case the command interface is not implemented properly. The diagram below illustrates the complete sequence.
Semi-transparent Legacy Radios
Some popular legacy radios (e.g. the SiK radio series) operate in semi-transparent mode by injecting RADIO_STATUS messages into the MAVLink message stream. Per MAVLink spec these should actually emit a heartbeat with the same system ID and a different component ID than the autopilot to be discoverable. However, an additional heartbeat could be an issue for deployed systems. Therefore these radios can alternatively confirm their MAVLink 2 compliance by emitting
RADIO_STATUS in v2 message format after receiving the first v2 MAVLink frame.