docs: def _send_control_message(self, cmd: int, value_or_length: int = 1, channel: int = 1,
                                data_or_length: Union[int, bytearray] = 1) -> int:
          """
          Sends a control transfer to the current device.
          :param cmd: 1 for single value transfer, 2 for multi-value transfer
          :param value_or_length: for single value transfer, the value. For multi-value transfer,
              the length of the data bytearray.
          :param channel: DMX channel number, 1- 512
          :param data_or_length: for a single value transfer it should be 1.
              For a multi-value transfer, a bytearray containing the values.
          :return: number of bytes sent.
          """
  
          if self._dev is None:
              raise ValueError("No usb device opened")
  
          # All data transfers use this request type. This is more for
          # the PyUSB package than for the uDMX as the uDMX does not
          # use it..
          bmRequestType = usb.util.CTRL_TYPE_VENDOR | usb.util.CTRL_RECIPIENT_DEVICE | usb.util.CTRL_OUT
  
          """
          usb request for SetSingleChannel:
              Request Type:   ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
              Request:        1
              Value:          value to set [0 .. 255]
              Index:          channel index to set [0 .. 511], not the human known value of 1-512
              Length:         ignored, but returned as the number of byte values transfered
          usb request for SetMultiChannel:
              Request Type:   ignored by device, should be USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_ENDPOINT_OUT
              Request:        2
              Value:          number of channels to set [1 .. 512-wIndex]
              Index:          index of first channel to set [0 .. 511], not the human known value of 1-512
              Data:           iterable object containing values (we use a bytearray)
          """
  
          n = self._dev.ctrl_transfer(bmRequestType, cmd, wValue=value_or_length, wIndex=channel - 1,
                                      data_or_wLength=data_or_length)
  
          # For a single value transfer the return value is the data_or_length value.
          # For a multi-value transfer the return value is the number of values transfer
          # which should be the number of values in the data_or_length bytearray.
          return n