/arch/arm/mach-msm/rpc_server_time_remote.c
C | 167 lines | 126 code | 22 blank | 19 comment | 11 complexity | 9863dfc31605e78af150661802e5761b MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
1/* arch/arm/mach-msm/rpc_server_time_remote.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2009-2010 Code Aurora Forum. All rights reserved.
5 * Author: Iliyan Malchev <ibm@android.com>
6 *
7 * This software is licensed under the terms of the GNU General Public
8 * License version 2, as published by the Free Software Foundation, and
9 * may be copied, distributed, and modified under those terms.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/kernel.h>
20#include <linux/err.h>
21#include <mach/msm_rpcrouter.h>
22#include "rpc_server_time_remote.h"
23#include <linux/rtc.h>
24#include <linux/android_alarm.h>
25
26/* time_remote_mtoa server definitions. */
27
28#define TIME_REMOTE_MTOA_PROG 0x3000005d
29#define TIME_REMOTE_MTOA_VERS_OLD 0
30#define TIME_REMOTE_MTOA_VERS 0x9202a8e4
31#define TIME_REMOTE_MTOA_VERS_COMP 0x00010002
32#define RPC_TIME_REMOTE_MTOA_NULL 0
33#define RPC_TIME_TOD_SET_APPS_BASES 2
34#define RPC_TIME_GET_APPS_USER_TIME 3
35
36struct rpc_time_tod_set_apps_bases_args {
37 uint32_t tick;
38 uint64_t stamp;
39};
40
41static int read_rtc0_time(struct msm_rpc_server *server,
42 struct rpc_request_hdr *req,
43 unsigned len)
44{
45 int err;
46 unsigned long tm_sec;
47 uint32_t size = 0;
48 void *reply;
49 uint32_t output_valid;
50 uint32_t rpc_status = RPC_ACCEPTSTAT_SYSTEM_ERR;
51 struct rtc_time tm;
52 struct rtc_device *rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE);
53
54 if (rtc == NULL) {
55 pr_err("%s: unable to open rtc device (%s)\n",
56 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
57 goto send_reply;
58 }
59
60 err = rtc_read_time(rtc, &tm);
61 if (err) {
62 pr_err("%s: Error reading rtc device (%s) : %d\n",
63 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE, err);
64 goto close_dev;
65 }
66
67 err = rtc_valid_tm(&tm);
68 if (err) {
69 pr_err("%s: Invalid RTC time (%s)\n",
70 __FILE__, CONFIG_RTC_HCTOSYS_DEVICE);
71 goto close_dev;
72 }
73
74 rtc_tm_to_time(&tm, &tm_sec);
75 rpc_status = RPC_ACCEPTSTAT_SUCCESS;
76
77close_dev:
78 rtc_class_close(rtc);
79
80send_reply:
81 reply = msm_rpc_server_start_accepted_reply(server, req->xid,
82 rpc_status);
83 if (rpc_status == RPC_ACCEPTSTAT_SUCCESS) {
84 output_valid = *((uint32_t *)(req + 1));
85 *(uint32_t *)reply = output_valid;
86 size = sizeof(uint32_t);
87 if (be32_to_cpu(output_valid)) {
88 reply += sizeof(uint32_t);
89 *(uint32_t *)reply = cpu_to_be32(tm_sec);
90 size += sizeof(uint32_t);
91 }
92 }
93 err = msm_rpc_server_send_accepted_reply(server, size);
94 if (err)
95 pr_err("%s: send accepted reply failed: %d\n", __func__, err);
96
97 return 1;
98}
99
100static int handle_rpc_call(struct msm_rpc_server *server,
101 struct rpc_request_hdr *req, unsigned len)
102{
103 struct timespec ts, tv;
104
105 switch (req->procedure) {
106 case RPC_TIME_REMOTE_MTOA_NULL:
107 return 0;
108
109 case RPC_TIME_TOD_SET_APPS_BASES: {
110 struct rpc_time_tod_set_apps_bases_args *args;
111 args = (struct rpc_time_tod_set_apps_bases_args *)(req + 1);
112 args->tick = be32_to_cpu(args->tick);
113 args->stamp = be64_to_cpu(args->stamp);
114 printk(KERN_INFO "RPC_TIME_TOD_SET_APPS_BASES:\n"
115 "\ttick = %d\n"
116 "\tstamp = %lld\n",
117 args->tick, args->stamp);
118
119 getnstimeofday(&ts);
120 rtc_hctosys();
121 getnstimeofday(&tv);
122 /* Update the alarm information with the new time info. */
123 alarm_update_timedelta(ts, tv);
124 return 0;
125 }
126
127 case RPC_TIME_GET_APPS_USER_TIME:
128 return read_rtc0_time(server, req, len);
129
130 default:
131 return -ENODEV;
132 }
133}
134
135static struct msm_rpc_server rpc_server[] = {
136 {
137 .prog = TIME_REMOTE_MTOA_PROG,
138 .vers = TIME_REMOTE_MTOA_VERS_OLD,
139 .rpc_call = handle_rpc_call,
140 },
141 {
142 .prog = TIME_REMOTE_MTOA_PROG,
143 .vers = TIME_REMOTE_MTOA_VERS,
144 .rpc_call = handle_rpc_call,
145 },
146 {
147 .prog = TIME_REMOTE_MTOA_PROG,
148 .vers = TIME_REMOTE_MTOA_VERS_COMP,
149 .rpc_call = handle_rpc_call,
150 },
151};
152
153static int __init rpc_server_init(void)
154{
155 /* Dual server registration to support backwards compatibility vers */
156 int ret;
157 ret = msm_rpc_create_server(&rpc_server[2]);
158 if (ret < 0)
159 return ret;
160 ret = msm_rpc_create_server(&rpc_server[1]);
161 if (ret < 0)
162 return ret;
163 return msm_rpc_create_server(&rpc_server[0]);
164}
165
166
167module_init(rpc_server_init);