static int s3fwrn5_fw_enter_update_mode()

in s3fwrn5/firmware.c [109:180]


static int s3fwrn5_fw_enter_update_mode(struct s3fwrn5_fw_info *fw_info,
	const void *hash_data, u16 hash_size,
	const void *sig_data, u16 sig_size)
{
	struct s3fwrn5_fw_cmd_enter_updatemode args;
	struct sk_buff *msg, *rsp = NULL;
	struct s3fwrn5_fw_header *hdr;
	int ret;

	/* Send ENTER_UPDATE_MODE command */

	args.hashcode_size = hash_size;
	args.signature_size = sig_size;

	ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_CMD,
		S3FWRN5_FW_CMD_ENTER_UPDATE_MODE, &args, sizeof(args));
	if (ret < 0)
		return ret;

	ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
	kfree_skb(msg);
	if (ret < 0)
		return ret;

	hdr = (struct s3fwrn5_fw_header *) rsp->data;
	if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
		ret = -EPROTO;
		goto out;
	}

	kfree_skb(rsp);

	/* Send hashcode data */

	ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0,
		hash_data, hash_size);
	if (ret < 0)
		return ret;

	ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
	kfree_skb(msg);
	if (ret < 0)
		return ret;

	hdr = (struct s3fwrn5_fw_header *) rsp->data;
	if (hdr->code != S3FWRN5_FW_RET_SUCCESS) {
		ret = -EPROTO;
		goto out;
	}

	kfree_skb(rsp);

	/* Send signature data */

	ret = s3fwrn5_fw_prep_msg(fw_info, &msg, S3FWRN5_FW_MSG_DATA, 0,
		sig_data, sig_size);
	if (ret < 0)
		return ret;

	ret = s3fwrn5_fw_send_msg(fw_info, msg, &rsp);
	kfree_skb(msg);
	if (ret < 0)
		return ret;

	hdr = (struct s3fwrn5_fw_header *) rsp->data;
	if (hdr->code != S3FWRN5_FW_RET_SUCCESS)
		ret = -EPROTO;

out:
	kfree_skb(rsp);
	return ret;
}