/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

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