samples/qmi/qmi_sample_client.c

Source file repositories/reference/linux-study-clean/samples/qmi/qmi_sample_client.c

File Facts

System
Linux kernel
Corpus path
samples/qmi/qmi_sample_client.c
Extension
.c
Size
14565 bytes
Lines
621
Domain
Support Tooling And Documentation
Bucket
samples
Inferred role
Support Tooling And Documentation: operation-table or driver-model contract
Status
pattern implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

static const struct file_operations ping_fops = {
	.open = simple_open,
	.write = ping_write,
};

static void ping_pong_cb(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
			 struct qmi_txn *txn, const void *data)
{
	const struct test_ping_resp_msg_v01 *resp = data;

	if (!txn) {
		pr_err("spurious ping response\n");
		return;
	}

	if (resp->resp.result == QMI_RESULT_FAILURE_V01)
		txn->result = -ENXIO;
	else if (!resp->pong_valid || memcmp(resp->pong, "pong", 4))
		txn->result = -EINVAL;

	complete(&txn->completion);
}

/*
 * data_write() - data debugfs file write handler
 * @file:	debugfs file context
 * @user_buf:	reference to the user data
 * @count:	number of bytes in @user_buf
 * @ppos:	offset in @file to write
 *
 * This function allows user space to send out a data QMI encoded message to
 * the associated remote test service and will return with the result of the
 * transaction. It serves as an example of how to have the QMI helpers decode a
 * transaction response into a provided object automatically.
 *
 * Return: @count, or negative errno on failure.
 */
static ssize_t data_write(struct file *file, const char __user *user_buf,
			  size_t count, loff_t *ppos)

{
	struct qmi_handle *qmi = file->private_data;
	struct test_data_resp_msg_v01 *resp;
	struct test_data_req_msg_v01 *req;
	struct qmi_txn txn;
	int ret;

	req = kzalloc(sizeof(*req), GFP_KERNEL);
	if (!req)
		return -ENOMEM;

	resp = kzalloc(sizeof(*resp), GFP_KERNEL);
	if (!resp) {
		kfree(req);
		return -ENOMEM;
	}

	req->data_len = min_t(size_t, sizeof(req->data), count);
	if (copy_from_user(req->data, user_buf, req->data_len)) {
		ret = -EFAULT;
		goto out;
	}

	ret = qmi_txn_init(qmi, &txn, test_data_resp_msg_v01_ei, resp);
	if (ret < 0)
		goto out;

	ret = qmi_send_request(qmi, NULL, &txn,
			       TEST_DATA_REQ_MSG_ID_V01,
			       TEST_DATA_REQ_MAX_MSG_LEN_V01,
			       test_data_req_msg_v01_ei, req);
	if (ret < 0) {
		qmi_txn_cancel(&txn);
		goto out;
	}

	ret = qmi_txn_wait(&txn, 5 * HZ);
	if (ret < 0) {
		goto out;
	} else if (!resp->data_valid ||
		   resp->data_len != req->data_len ||
		   memcmp(resp->data, req->data, req->data_len)) {
		pr_err("response data doesn't match expectation\n");
		ret = -EINVAL;
		goto out;
	}

	ret = count;

out:

Annotation

Implementation Notes