Handles the protocol for sending data to the device.

    Arguments:
      source_file: File-object to read from for the device.
      source_len: Amount of data, in bytes, to send to the device.
      info_cb: Optional callback for text sent from the bootloader.
      progress_callback: Callback that takes the current and the total progress
        of the current file.
      timeout_ms: Timeout in milliseconds to wait for each response.

    Raises:
      FastbootTransferError: When fastboot can't handle this amount of data.
      FastbootStateMismatch: Fastboot responded with the wrong packet type.
      FastbootRemoteFailure: Fastboot reported failure.
      FastbootInvalidResponse: Fastboot responded with an unknown packet type.

    Returns:
      OKAY packet's message.

def handle_data_sending(self, source_file, source_len,
                          info_cb=DEFAULT_MESSAGE_CALLBACK,
                          progress_callback=None, timeout_ms=None):
    """Handles the protocol for sending data to the device.

    Arguments:
      source_file: File-object to read from for the device.
      source_len: Amount of data, in bytes, to send to the device.
      info_cb: Optional callback for text sent from the bootloader.
      progress_callback: Callback that takes the current and the total progress
        of the current file.
      timeout_ms: Timeout in milliseconds to wait for each response.

    Raises:
      FastbootTransferError: When fastboot can't handle this amount of data.
      FastbootStateMismatch: Fastboot responded with the wrong packet type.
      FastbootRemoteFailure: Fastboot reported failure.
      FastbootInvalidResponse: Fastboot responded with an unknown packet type.

    Returns:
      OKAY packet's message.
    """
    accepted_size = self._accept_responses(
        'DATA', info_cb, timeout_ms=timeout_ms)

    accepted_size = binascii.unhexlify(accepted_size[:8])
    accepted_size, = struct.unpack('>I', accepted_size)
    if accepted_size != source_len:
      raise usb_exceptions.FastbootTransferError(
          'Device refused to download %s bytes of data (accepts %s bytes)',
          source_len, accepted_size)
    self._write(source_file, accepted_size, progress_callback)
    return self._accept_responses('OKAY', info_cb, timeout_ms=timeout_ms)