blob: 609b1258bfbdb586b54884aed23243a9a23f5e79 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14/*
15 * DOG KEEPALIVE RPC CLIENT MODULE
16 */
17
18#include <linux/slab.h>
19#include <linux/module.h>
20#include <linux/kernel.h>
21#include <linux/err.h>
22#include <mach/msm_rpcrouter.h>
23
24#define DOG_KEEPALIVE_PROG 0x300000A2
25#define DOG_KEEPALIVE_VERS 0x00010001
26
27#define DOG_KEEPALIVE_REGISTER_PROC 2
28#define DOG_KEEPALIVE_UNREGISTER_PROC 3
29
30#define DOG_KEEPALIVE_CB_PROC 1
31
32static int dog_keepalive_debug;
33module_param_named(debug, dog_keepalive_debug,
34 int, S_IRUGO | S_IWUSR | S_IWGRP);
35
36#if defined(DEBUG)
37#define DBG(x...) do { \
38 if (dog_keepalive_debug) \
39 printk(KERN_INFO x); \
40 } while (0)
41#else
42#define DBG(x...) do { } while (0)
43#endif
44
45static struct msm_rpc_client *dog_keepalive_rpc_client;
46static int32_t dog_clnt_id = -1;
47
48struct dog_keepalive_cb_arg {
49 uint32_t cb_id;
50};
51
52struct dog_keepalive_cb_ret {
53 uint32_t result;
54};
55
56static int dog_keepalive_cb(struct msm_rpc_client *client,
57 struct msm_rpc_xdr *xdr)
58{
59 int rc;
60 void *cb_func;
61 uint32_t accept_status;
62 struct dog_keepalive_cb_arg arg;
63 struct dog_keepalive_cb_ret ret;
64
65 xdr_recv_uint32(xdr, &arg.cb_id); /* cb_id */
66
67 cb_func = msm_rpc_get_cb_func(client, arg.cb_id);
68 if (cb_func) {
69 rc = ((int (*)
70 (struct dog_keepalive_cb_arg *,
71 struct dog_keepalive_cb_ret *))
72 cb_func)(&arg, &ret);
73 if (rc)
74 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
75 else
76 accept_status = RPC_ACCEPTSTAT_SUCCESS;
77 } else
78 accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
79
80 xdr_start_accepted_reply(xdr, accept_status);
81
82 if (accept_status == RPC_ACCEPTSTAT_SUCCESS)
83 xdr_send_uint32(xdr, &ret.result); /* result */
84
85 rc = xdr_send_msg(xdr);
86 if (rc)
87 pr_err("%s: send accepted reply failed: %d\n", __func__, rc);
88
89 return rc;
90}
91
92static int dog_keepalive_cb_func(struct msm_rpc_client *client,
93 struct rpc_request_hdr *req,
94 struct msm_rpc_xdr *xdr)
95{
96 int rc = 0;
97
98 switch (req->procedure) {
99 case DOG_KEEPALIVE_CB_PROC:
100 rc = dog_keepalive_cb(client, xdr);
101 break;
102 default:
103 pr_err("%s: procedure not supported %d\n",
104 __func__, req->procedure);
105 xdr_start_accepted_reply(xdr, RPC_ACCEPTSTAT_PROC_UNAVAIL);
106 rc = xdr_send_msg(xdr);
107 if (rc)
108 pr_err("%s: sending reply failed: %d\n", __func__, rc);
109 break;
110 }
111 return rc;
112}
113
114struct dog_keepalive_register_arg {
115 int (*cb_func)(
116 struct dog_keepalive_cb_arg *arg,
117 struct dog_keepalive_cb_ret *ret);
118 uint32_t response_msec;
119 uint32_t clnt_id_valid;
120};
121
122struct dog_keepalive_register_ret {
123 uint32_t *clnt_id;
124 uint32_t result;
125};
126
127static int dog_keepalive_register_arg_func(struct msm_rpc_client *client,
128 struct msm_rpc_xdr *xdr, void *data)
129{
130 struct dog_keepalive_register_arg *arg = data;
131 int cb_id;
132
133 /* cb_func */
134 cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
135 if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
136 return cb_id;
137
138 xdr_send_uint32(xdr, &cb_id);
139 xdr_send_uint32(xdr, &arg->response_msec); /* response_msec */
140 xdr_send_uint32(xdr, &arg->clnt_id_valid); /* clnt_id valid */
141 return 0;
142}
143
144static int dog_keepalive_register_ret_func(struct msm_rpc_client *client,
145 struct msm_rpc_xdr *xdr, void *data)
146{
147 struct dog_keepalive_register_ret *ret = data;
148
149 /* clnt_id */
150 xdr_recv_pointer(xdr, (void **)&(ret->clnt_id), sizeof(uint32_t),
151 xdr_recv_uint32);
152
153 /* result */
154 xdr_recv_uint32(xdr, &ret->result);
155 return 0;
156}
157
158static int dog_keepalive_register_func(struct msm_rpc_client *client,
159 struct dog_keepalive_register_arg *arg,
160 struct dog_keepalive_register_ret *ret)
161{
162 return msm_rpc_client_req2(client,
163 DOG_KEEPALIVE_REGISTER_PROC,
164 dog_keepalive_register_arg_func, arg,
165 dog_keepalive_register_ret_func, ret, -1);
166}
167
168static int dog_keepalive_cb_proc_func(struct dog_keepalive_cb_arg *arg,
169 struct dog_keepalive_cb_ret *ret)
170{
171 DBG("%s: received, client %d \n", __func__, dog_clnt_id);
172 ret->result = 1;
173 return 0;
174}
175
176static void dog_keepalive_register(void)
177{
178 struct dog_keepalive_register_arg arg;
179 struct dog_keepalive_register_ret ret;
180 int rc;
181
182 arg.cb_func = dog_keepalive_cb_proc_func;
183 arg.response_msec = 1000;
184 arg.clnt_id_valid = 1;
185 ret.clnt_id = NULL;
186 rc = dog_keepalive_register_func(dog_keepalive_rpc_client,
187 &arg, &ret);
188 if (rc)
189 pr_err("%s: register request failed\n", __func__);
190 else
191 dog_clnt_id = *ret.clnt_id;
192
193 kfree(ret.clnt_id);
194 DBG("%s: register complete\n", __func__);
195}
196
197/* Registration with the platform driver for notification on the availability
198 * of the DOG_KEEPALIVE remote server
199 */
200static int dog_keepalive_init_probe(struct platform_device *pdev)
201{
202 DBG("%s: probe called\n", __func__);
203 dog_keepalive_rpc_client = msm_rpc_register_client2(
204 "dog-keepalive",
205 DOG_KEEPALIVE_PROG,
206 DOG_KEEPALIVE_VERS,
207 0, dog_keepalive_cb_func);
208
209 if (IS_ERR(dog_keepalive_rpc_client)) {
210 pr_err("%s: RPC client creation failed\n", __func__);
211 return PTR_ERR(dog_keepalive_rpc_client);
212 }
213
214 /* Send RPC call to register for callbacks */
215 dog_keepalive_register();
216
217 return 0;
218}
219
220static char dog_keepalive_driver_name[] = "rs00000000";
221
222static struct platform_driver dog_keepalive_init_driver = {
223 .probe = dog_keepalive_init_probe,
224 .driver = {
225 .owner = THIS_MODULE,
226 },
227};
228
229static int __init rpc_dog_keepalive_init(void)
230{
231 snprintf(dog_keepalive_driver_name, sizeof(dog_keepalive_driver_name),
232 "rs%08x", DOG_KEEPALIVE_PROG);
233 dog_keepalive_init_driver.driver.name = dog_keepalive_driver_name;
234
235 return platform_driver_register(&dog_keepalive_init_driver);
236}
237
238late_initcall(rpc_dog_keepalive_init);
239MODULE_DESCRIPTION("DOG KEEPALIVE RPC CLIENT");
240MODULE_LICENSE("GPL v2");