PageRenderTime 56ms CodeModel.GetById 18ms app.highlight 32ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/arm/mach-fsm/oem_rapi_client.c

https://bitbucket.org/sammyz/iscream_thunderc-2.6.35-rebase
C | 359 lines | 271 code | 63 blank | 25 comment | 36 complexity | 31b869674460faf7cf8fffb00f8795db MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/* Copyright (c) 2009-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 * You should have received a copy of the GNU General Public License
 13 * along with this program; if not, write to the Free Software
 14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 15 * 02110-1301, USA.
 16 *
 17 */
 18
 19/*
 20 * OEM RAPI CLIENT Driver source file
 21 */
 22
 23#include <linux/kernel.h>
 24#include <linux/err.h>
 25#include <linux/fs.h>
 26#include <linux/sched.h>
 27#include <linux/debugfs.h>
 28#include <linux/uaccess.h>
 29#include <linux/delay.h>
 30#include <mach/msm_rpcrouter.h>
 31#include <mach/oem_rapi_client.h>
 32
 33#define OEM_RAPI_PROG  0x3000006B
 34#define OEM_RAPI_VERS  0x00010001
 35
 36#define OEM_RAPI_NULL_PROC                        0
 37#define OEM_RAPI_RPC_GLUE_CODE_INFO_REMOTE_PROC   1
 38#define OEM_RAPI_STREAMING_FUNCTION_PROC          2
 39
 40#define OEM_RAPI_CLIENT_MAX_OUT_BUFF_SIZE 128
 41
 42static struct msm_rpc_client *rpc_client;
 43static uint32_t open_count;
 44static DEFINE_MUTEX(oem_rapi_client_lock);
 45
 46/* TODO: check where to allocate memory for return */
 47static int oem_rapi_client_cb(struct msm_rpc_client *client,
 48			      struct rpc_request_hdr *req,
 49			      struct msm_rpc_xdr *xdr)
 50{
 51	uint32_t cb_id, accept_status;
 52	int rc;
 53	void *cb_func;
 54	uint32_t temp;
 55
 56	struct oem_rapi_client_streaming_func_cb_arg arg;
 57	struct oem_rapi_client_streaming_func_cb_ret ret;
 58
 59	arg.input = NULL;
 60	ret.out_len = NULL;
 61	ret.output = NULL;
 62
 63	xdr_recv_uint32(xdr, &cb_id);                    /* cb_id */
 64	xdr_recv_uint32(xdr, &arg.event);                /* enum */
 65	xdr_recv_uint32(xdr, (uint32_t *)(&arg.handle)); /* handle */
 66	xdr_recv_uint32(xdr, &arg.in_len);               /* in_len */
 67	xdr_recv_bytes(xdr, (void **)&arg.input, &temp); /* input */
 68	xdr_recv_uint32(xdr, &arg.out_len_valid);        /* out_len */
 69	if (arg.out_len_valid) {
 70		ret.out_len = kmalloc(sizeof(*ret.out_len), GFP_KERNEL);
 71		if (!ret.out_len) {
 72			accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
 73			goto oem_rapi_send_ack;
 74		}
 75	}
 76
 77	xdr_recv_uint32(xdr, &arg.output_valid);         /* out */
 78	if (arg.output_valid) {
 79		xdr_recv_uint32(xdr, &arg.output_size);  /* ouput_size */
 80
 81		ret.output = kmalloc(arg.output_size, GFP_KERNEL);
 82		if (!ret.output) {
 83			accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
 84			goto oem_rapi_send_ack;
 85		}
 86	}
 87
 88	cb_func = msm_rpc_get_cb_func(client, cb_id);
 89	if (cb_func) {
 90		rc = ((int (*)(struct oem_rapi_client_streaming_func_cb_arg *,
 91			       struct oem_rapi_client_streaming_func_cb_ret *))
 92		      cb_func)(&arg, &ret);
 93		if (rc)
 94			accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
 95		else
 96			accept_status = RPC_ACCEPTSTAT_SUCCESS;
 97	} else
 98		accept_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
 99
100 oem_rapi_send_ack:
101	xdr_start_accepted_reply(xdr, accept_status);
102
103	if (accept_status == RPC_ACCEPTSTAT_SUCCESS) {
104		uint32_t temp = sizeof(uint32_t);
105		xdr_send_pointer(xdr, (void **)&(ret.out_len), temp,
106				 xdr_send_uint32);
107
108		/* output */
109		if (ret.output && ret.out_len)
110			xdr_send_bytes(xdr, (const void **)&ret.output,
111					     ret.out_len);
112		else {
113			temp = 0;
114			xdr_send_uint32(xdr, &temp);
115		}
116	}
117	rc = xdr_send_msg(xdr);
118	if (rc)
119		pr_err("%s: sending reply failed: %d\n", __func__, rc);
120
121	kfree(arg.input);
122	kfree(ret.out_len);
123	kfree(ret.output);
124
125	return 0;
126}
127
128static int oem_rapi_client_streaming_function_arg(struct msm_rpc_client *client,
129						  struct msm_rpc_xdr *xdr,
130						  void *data)
131{
132	int cb_id;
133	struct oem_rapi_client_streaming_func_arg *arg = data;
134
135	cb_id = msm_rpc_add_cb_func(client, (void *)arg->cb_func);
136	if ((cb_id < 0) && (cb_id != MSM_RPC_CLIENT_NULL_CB_ID))
137		return cb_id;
138
139	xdr_send_uint32(xdr, &arg->event);                /* enum */
140	xdr_send_uint32(xdr, &cb_id);                     /* cb_id */
141	xdr_send_uint32(xdr, (uint32_t *)(&arg->handle)); /* handle */
142	xdr_send_uint32(xdr, &arg->in_len);               /* in_len */
143	xdr_send_bytes(xdr, (const void **)&arg->input,
144			     &arg->in_len);                     /* input */
145	xdr_send_uint32(xdr, &arg->out_len_valid);        /* out_len */
146	xdr_send_uint32(xdr, &arg->output_valid);         /* output */
147
148	/* output_size */
149	if (arg->output_valid)
150		xdr_send_uint32(xdr, &arg->output_size);
151
152	return 0;
153}
154
155static int oem_rapi_client_streaming_function_ret(struct msm_rpc_client *client,
156						  struct msm_rpc_xdr *xdr,
157						  void *data)
158{
159	struct oem_rapi_client_streaming_func_ret *ret = data;
160	uint32_t temp;
161
162	/* out_len */
163	xdr_recv_pointer(xdr, (void **)&(ret->out_len), sizeof(uint32_t),
164			 xdr_recv_uint32);
165
166	/* output */
167	if (ret->out_len && *ret->out_len)
168		xdr_recv_bytes(xdr, (void **)&ret->output, &temp);
169
170	return 0;
171}
172
173int oem_rapi_client_streaming_function(
174	struct msm_rpc_client *client,
175	struct oem_rapi_client_streaming_func_arg *arg,
176	struct oem_rapi_client_streaming_func_ret *ret)
177{
178	return msm_rpc_client_req2(client,
179				   OEM_RAPI_STREAMING_FUNCTION_PROC,
180				   oem_rapi_client_streaming_function_arg, arg,
181				   oem_rapi_client_streaming_function_ret,
182				   ret, -1);
183}
184EXPORT_SYMBOL(oem_rapi_client_streaming_function);
185
186int oem_rapi_client_close(void)
187{
188	mutex_lock(&oem_rapi_client_lock);
189	if (--open_count == 0) {
190		msm_rpc_unregister_client(rpc_client);
191		pr_info("%s: disconnected from remote oem rapi server\n",
192			__func__);
193	}
194	mutex_unlock(&oem_rapi_client_lock);
195	return 0;
196}
197EXPORT_SYMBOL(oem_rapi_client_close);
198
199struct msm_rpc_client *oem_rapi_client_init(void)
200{
201	mutex_lock(&oem_rapi_client_lock);
202	if (open_count == 0) {
203		rpc_client = msm_rpc_register_client2("oemrapiclient",
204						      OEM_RAPI_PROG,
205						      OEM_RAPI_VERS, 0,
206						      oem_rapi_client_cb);
207		if (!IS_ERR(rpc_client))
208			open_count++;
209	}
210	mutex_unlock(&oem_rapi_client_lock);
211	return rpc_client;
212}
213EXPORT_SYMBOL(oem_rapi_client_init);
214
215#if defined(CONFIG_DEBUG_FS)
216
217static struct dentry *dent;
218static int oem_rapi_client_test_res;
219
220static int oem_rapi_client_null(struct msm_rpc_client *client,
221				void *arg, void *ret)
222{
223	return msm_rpc_client_req2(client, OEM_RAPI_NULL_PROC,
224				   NULL, NULL, NULL, NULL, -1);
225}
226
227static int oem_rapi_client_test_streaming_cb_func(
228	struct oem_rapi_client_streaming_func_cb_arg *arg,
229	struct oem_rapi_client_streaming_func_cb_ret *ret)
230{
231	uint32_t size;
232
233	size = (arg->in_len < OEM_RAPI_CLIENT_MAX_OUT_BUFF_SIZE) ?
234		arg->in_len : OEM_RAPI_CLIENT_MAX_OUT_BUFF_SIZE;
235
236	if (ret->out_len != 0)
237		*ret->out_len = size;
238
239	if (ret->output != 0)
240		memcpy(ret->output, arg->input, size);
241
242	return 0;
243}
244
245static ssize_t debug_read(struct file *fp, char __user *buf,
246			  size_t count, loff_t *pos)
247{
248	char _buf[16];
249
250	snprintf(_buf, sizeof(_buf), "%i\n", oem_rapi_client_test_res);
251
252	return simple_read_from_buffer(buf, count, pos, _buf, strlen(_buf));
253}
254
255static ssize_t debug_write(struct file *fp, const char __user *buf,
256			   size_t count, loff_t *pos)
257{
258	char input[OEM_RAPI_CLIENT_MAX_OUT_BUFF_SIZE];
259	struct oem_rapi_client_streaming_func_arg arg;
260	struct oem_rapi_client_streaming_func_ret ret;
261
262	unsigned char cmd[64];
263	int len;
264
265	if (count < 1)
266		return 0;
267
268	len = count > 63 ? 63 : count;
269
270	if (copy_from_user(cmd, buf, len))
271		return -EFAULT;
272
273	cmd[len] = 0;
274
275	if (cmd[len-1] == '\n') {
276		cmd[len-1] = 0;
277		len--;
278	}
279
280	if (!strncmp(cmd, "null", 64)) {
281		oem_rapi_client_test_res = oem_rapi_client_null(rpc_client,
282								NULL, NULL);
283	} else if (!strncmp(cmd, "streaming_func", 64)) {
284		memset(input, 5, 16);
285		arg.event = 0;
286		arg.cb_func = oem_rapi_client_test_streaming_cb_func;
287		arg.handle = (void *)20;
288		arg.in_len = 16;
289		arg.input = input;
290		arg.out_len_valid = 1;
291		arg.output_valid = 1;
292		arg.output_size = OEM_RAPI_CLIENT_MAX_OUT_BUFF_SIZE;
293		ret.out_len = NULL;
294		ret.output = NULL;
295
296		oem_rapi_client_test_res = oem_rapi_client_streaming_function(
297			rpc_client, &arg, &ret);
298
299		kfree(ret.out_len);
300		kfree(ret.output);
301
302	} else
303		oem_rapi_client_test_res = -EINVAL;
304
305	if (oem_rapi_client_test_res)
306		pr_err("oem rapi client test fail %d\n",
307		       oem_rapi_client_test_res);
308	else
309		pr_info("oem rapi client test passed\n");
310
311	return count;
312}
313
314static int debug_release(struct inode *ip, struct file *fp)
315{
316	return oem_rapi_client_close();
317}
318
319static int debug_open(struct inode *ip, struct file *fp)
320{
321	struct msm_rpc_client *client;
322	client = oem_rapi_client_init();
323	if (IS_ERR(client)) {
324		pr_err("%s: couldn't open oem rapi client\n", __func__);
325		return PTR_ERR(client);
326	} else
327		pr_info("%s: connected to remote oem rapi server\n", __func__);
328
329	return 0;
330}
331
332static const struct file_operations debug_ops = {
333	.owner = THIS_MODULE,
334	.open = debug_open,
335	.release = debug_release,
336	.read = debug_read,
337	.write = debug_write,
338};
339
340static void __exit oem_rapi_client_mod_exit(void)
341{
342	debugfs_remove(dent);
343}
344
345static int __init oem_rapi_client_mod_init(void)
346{
347	dent = debugfs_create_file("oem_rapi", 0444, 0, NULL, &debug_ops);
348	open_count = 0;
349	oem_rapi_client_test_res = -1;
350	return 0;
351}
352
353module_init(oem_rapi_client_mod_init);
354module_exit(oem_rapi_client_mod_exit);
355
356#endif
357
358MODULE_DESCRIPTION("OEM RAPI CLIENT Driver");
359MODULE_LICENSE("GPL v2");