Initial Contribution

msm-2.6.38: tag AU_LINUX_ANDROID_GINGERBREAD.02.03.04.00.142

Signed-off-by: Bryan Huntsman <bryanh@codeaurora.org>
diff --git a/arch/arm/mach-msm/rpc_dog_keepalive.c b/arch/arm/mach-msm/rpc_dog_keepalive.c
new file mode 100644
index 0000000..609b125
--- /dev/null
+++ b/arch/arm/mach-msm/rpc_dog_keepalive.c
@@ -0,0 +1,240 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * DOG KEEPALIVE RPC CLIENT MODULE
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <mach/msm_rpcrouter.h>
+
+#define DOG_KEEPALIVE_PROG 0x300000A2
+#define DOG_KEEPALIVE_VERS 0x00010001
+
+#define DOG_KEEPALIVE_REGISTER_PROC      2
+#define DOG_KEEPALIVE_UNREGISTER_PROC    3
+
+#define DOG_KEEPALIVE_CB_PROC            1
+
+static int dog_keepalive_debug;
+module_param_named(debug, dog_keepalive_debug,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#if defined(DEBUG)
+#define DBG(x...)  do {		                \
+		if (dog_keepalive_debug)	\
+			printk(KERN_INFO x);	\
+	} while (0)
+#else
+#define DBG(x...) do { } while (0)
+#endif
+
+static struct msm_rpc_client *dog_keepalive_rpc_client;
+static int32_t dog_clnt_id = -1;
+
+struct dog_keepalive_cb_arg {
+	uint32_t cb_id;
+};
+
+struct dog_keepalive_cb_ret {
+	uint32_t result;
+};
+
+static int dog_keepalive_cb(struct msm_rpc_client *client,
+			    struct msm_rpc_xdr *xdr)
+{
+	int rc;
+	void *cb_func;
+	uint32_t accept_status;
+	struct dog_keepalive_cb_arg arg;
+	struct dog_keepalive_cb_ret ret;
+
+	xdr_recv_uint32(xdr, &arg.cb_id);           /* cb_id */
+
+	cb_func = msm_rpc_get_cb_func(client, arg.cb_id);
+	if (cb_func) {
+		rc = ((int (*)
+		       (struct dog_keepalive_cb_arg *,
+			struct dog_keepalive_cb_ret *))
+		      cb_func)(&arg, &ret);
+		if (rc)
+			accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
+		else
+			accept_status = RPC_ACCEPTSTAT_SUCCESS;
+	} else
+		accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
+
+	xdr_start_accepted_reply(xdr, accept_status);
+
+	if (accept_status == RPC_ACCEPTSTAT_SUCCESS)
+		xdr_send_uint32(xdr, &ret.result);         /* result */
+
+	rc = xdr_send_msg(xdr);
+	if (rc)
+		pr_err("%s: send accepted reply failed: %d\n", __func__, rc);
+
+	return rc;
+}
+
+static int dog_keepalive_cb_func(struct msm_rpc_client *client,
+				 struct rpc_request_hdr *req,
+				 struct msm_rpc_xdr *xdr)
+{
+	int rc = 0;
+
+	switch (req->procedure) {
+	case DOG_KEEPALIVE_CB_PROC:
+		rc = dog_keepalive_cb(client, xdr);
+		break;
+	default:
+		pr_err("%s: procedure not supported %d\n",
+		       __func__, req->procedure);
+		xdr_start_accepted_reply(xdr, RPC_ACCEPTSTAT_PROC_UNAVAIL);
+		rc = xdr_send_msg(xdr);
+		if (rc)
+			pr_err("%s: sending reply failed: %d\n", __func__, rc);
+		break;
+	}
+	return rc;
+}
+
+struct dog_keepalive_register_arg {
+	int (*cb_func)(
+		struct dog_keepalive_cb_arg *arg,
+		struct dog_keepalive_cb_ret *ret);
+	uint32_t response_msec;
+	uint32_t clnt_id_valid;
+};
+
+struct dog_keepalive_register_ret {
+	uint32_t *clnt_id;
+	uint32_t result;
+};
+
+static int dog_keepalive_register_arg_func(struct msm_rpc_client *client,
+					   struct msm_rpc_xdr *xdr, void *data)
+{
+	struct dog_keepalive_register_arg *arg = data;
+	int cb_id;
+
+	/* cb_func */
+	cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
+	if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
+		return cb_id;
+
+	xdr_send_uint32(xdr, &cb_id);
+	xdr_send_uint32(xdr, &arg->response_msec);    /* response_msec */
+	xdr_send_uint32(xdr, &arg->clnt_id_valid);    /* clnt_id valid */
+	return 0;
+}
+
+static int dog_keepalive_register_ret_func(struct msm_rpc_client *client,
+					   struct msm_rpc_xdr *xdr, void *data)
+{
+	struct dog_keepalive_register_ret *ret = data;
+
+	/* clnt_id */
+	xdr_recv_pointer(xdr, (void **)&(ret->clnt_id), sizeof(uint32_t),
+			 xdr_recv_uint32);
+
+	/* result */
+	xdr_recv_uint32(xdr, &ret->result);
+	return 0;
+}
+
+static int dog_keepalive_register_func(struct msm_rpc_client *client,
+				       struct dog_keepalive_register_arg *arg,
+				       struct dog_keepalive_register_ret *ret)
+{
+	return msm_rpc_client_req2(client,
+				   DOG_KEEPALIVE_REGISTER_PROC,
+				   dog_keepalive_register_arg_func, arg,
+				   dog_keepalive_register_ret_func, ret, -1);
+}
+
+static int dog_keepalive_cb_proc_func(struct dog_keepalive_cb_arg *arg,
+				      struct dog_keepalive_cb_ret *ret)
+{
+	DBG("%s: received, client %d \n", __func__, dog_clnt_id);
+	ret->result = 1;
+	return 0;
+}
+
+static void dog_keepalive_register(void)
+{
+	struct dog_keepalive_register_arg arg;
+	struct dog_keepalive_register_ret ret;
+	int rc;
+
+	arg.cb_func = dog_keepalive_cb_proc_func;
+	arg.response_msec = 1000;
+	arg.clnt_id_valid = 1;
+	ret.clnt_id = NULL;
+	rc = dog_keepalive_register_func(dog_keepalive_rpc_client,
+					 &arg, &ret);
+	if (rc)
+		pr_err("%s: register request failed\n", __func__);
+	else
+		dog_clnt_id = *ret.clnt_id;
+
+	kfree(ret.clnt_id);
+	DBG("%s: register complete\n", __func__);
+}
+
+/* Registration with the platform driver for notification on the availability
+ * of the DOG_KEEPALIVE remote server
+ */
+static int dog_keepalive_init_probe(struct platform_device *pdev)
+{
+	DBG("%s: probe called\n", __func__);
+	dog_keepalive_rpc_client = msm_rpc_register_client2(
+		"dog-keepalive",
+		DOG_KEEPALIVE_PROG,
+		DOG_KEEPALIVE_VERS,
+		0, dog_keepalive_cb_func);
+
+	if (IS_ERR(dog_keepalive_rpc_client)) {
+		pr_err("%s: RPC client creation failed\n", __func__);
+		return PTR_ERR(dog_keepalive_rpc_client);
+	}
+
+	/* Send RPC call to register for callbacks */
+	dog_keepalive_register();
+
+	return 0;
+}
+
+static char dog_keepalive_driver_name[] = "rs00000000";
+
+static struct platform_driver dog_keepalive_init_driver = {
+	.probe = dog_keepalive_init_probe,
+	.driver = {
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init rpc_dog_keepalive_init(void)
+{
+	snprintf(dog_keepalive_driver_name, sizeof(dog_keepalive_driver_name),
+		 "rs%08x", DOG_KEEPALIVE_PROG);
+	dog_keepalive_init_driver.driver.name = dog_keepalive_driver_name;
+
+	return platform_driver_register(&dog_keepalive_init_driver);
+}
+
+late_initcall(rpc_dog_keepalive_init);
+MODULE_DESCRIPTION("DOG KEEPALIVE RPC CLIENT");
+MODULE_LICENSE("GPL v2");