2ef9e4f3772d51417a13f93f666237f52f3274e6
[samsung-ril.git] / misc.c
1 /**
2  * This file is part of samsung-ril.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2011 Paul Kocialkowski <contact@oaulk.fr>
6  *
7  * samsung-ril is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * samsung-ril is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with samsung-ril.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21
22 #define LOG_TAG "RIL-MISC"
23 #include <utils/Log.h>
24
25 #include "samsung-ril.h"
26 #include "util.h"
27
28 void ril_request_get_imei_send(RIL_Token t)
29 {
30         unsigned char data;
31
32         data = IPC_MISC_ME_SN_SERIAL_NUM;
33         ipc_fmt_send(IPC_MISC_ME_SN, IPC_TYPE_GET, (unsigned char *) &data, sizeof(data), reqGetId(t));
34 }
35
36 void ril_request_get_imei(RIL_Token t)
37 {
38         if(ril_state.tokens.get_imei) {
39                 LOGD("Another IMEI request is waiting, aborting");
40                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
41                 return;
42         }
43
44         ril_state.tokens.get_imei = t;
45
46         if(ril_state.tokens.get_imeisv) {
47                 LOGD("IMEISV token found: 0x%x", ril_state.tokens.get_imeisv);
48
49                 if(ril_state.radio_state != RADIO_STATE_OFF) {
50                         ril_request_get_imei_send(ril_state.tokens.get_imei);
51                 } else {
52                         LOGD("Radio is off, waiting");
53                 }
54         } else {
55                 LOGD("Waiting for IMEISV token");
56         }
57 }
58
59 void ril_request_get_imeisv(RIL_Token t)
60 {
61         if(ril_state.tokens.get_imeisv) {
62                 LOGD("Another IMEISV request is waiting, aborting");
63                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
64                 return;
65         }
66
67         ril_state.tokens.get_imeisv = t;
68
69         if(ril_state.tokens.get_imei) {
70                 LOGD("IMEI token found: 0x%x", ril_state.tokens.get_imei);
71
72                 if(ril_state.radio_state != RADIO_STATE_OFF) {
73                         ril_request_get_imei_send(ril_state.tokens.get_imei);
74                 } else {
75                         LOGD("Radio is off, waiting");
76                 }
77         } else {
78                 LOGD("Waiting for IMEI token");
79         }
80 }
81
82 void ipc_misc_me_sn_imei(RIL_Token t, void *data, int length)
83 {
84         struct ipc_misc_me_sn *imei_info;
85         char imei[33];
86         char imeisv[3];
87
88         imei_info = (struct ipc_misc_me_sn *) data;
89
90         if(ril_state.tokens.get_imei != t) 
91                 LOGE("IMEI tokens mismatch (0x%x and 0x%x)", ril_state.tokens.get_imei, t);
92
93         if(imei_info->length > 32)
94                 return;
95
96         memset(imei, 0, sizeof(imei));
97         memset(imeisv, 0, sizeof(imeisv));
98
99         memcpy(imei, imei_info->data, imei_info->length);
100
101         // Last two bytes of IMEI in imei_info are the SV bytes
102         memcpy(imeisv, (imei_info->data + imei_info->length - 2), 2);
103
104         // In case of token mismatch, complete both requests
105         if(t && ril_state.tokens.get_imei != t) {
106                 RIL_onRequestComplete(t, RIL_E_SUCCESS, imei, sizeof(char *));
107         }
108
109         // IMEI
110         if(ril_state.tokens.get_imei) {
111                 RIL_onRequestComplete(ril_state.tokens.get_imei, RIL_E_SUCCESS, imei, sizeof(char *));
112                 ril_state.tokens.get_imei = 0;
113         }
114
115         // IMEI SV
116         if(ril_state.tokens.get_imeisv) {
117                 RIL_onRequestComplete(ril_state.tokens.get_imeisv, RIL_E_SUCCESS, imeisv, sizeof(char *));
118                 ril_state.tokens.get_imeisv = 0;
119         }
120 }
121
122 void ipc_misc_me_sn(struct ipc_message_info *info)
123 {
124         struct ipc_misc_me_sn *me_sn_info = (struct ipc_misc_me_sn *) info->data;
125
126         switch(me_sn_info->type) {
127                 case IPC_MISC_ME_SN_SERIAL_NUM:
128                         ipc_misc_me_sn_imei(reqGetToken(info->aseq), info->data, info->length);
129                         break;
130                 case IPC_MISC_ME_SN_SERIAL_NUM_SERIAL:
131                         LOGD("Got IPC_MISC_ME_SN_SERIAL_NUM_SERIAL: %s\n", me_sn_info->data);
132                         break;
133         }
134 }
135
136 void ril_request_baseband_version(RIL_Token t)
137 {
138         unsigned char data;
139         if(ril_state.tokens.baseband_version) {
140                 LOGD("Another Baseband version request is waiting, aborting");
141                 RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
142                 return;
143         }
144
145         ril_state.tokens.baseband_version = t;
146
147         if(ril_state.radio_state != RADIO_STATE_OFF) {
148                 data = 0xff;
149
150                 ipc_fmt_send(IPC_MISC_ME_VERSION, IPC_TYPE_GET, (unsigned char *) &data, sizeof(data), reqGetId(t));
151         }
152 }
153
154 void ipc_misc_me_version(struct ipc_message_info *info)
155 {
156         char sw_version[33];
157         struct ipc_misc_me_version *version = (struct ipc_misc_me_version *) info->data;
158         RIL_Token t = reqGetToken(info->aseq);
159
160         if(ril_state.tokens.baseband_version != t) 
161                 LOGE("Baseband tokens mismatch (0x%x and 0x%x)", ril_state.tokens.baseband_version, t);
162
163         memcpy(sw_version, version->sw_version, 32);
164         sw_version[32] = '\0';
165
166         RIL_onRequestComplete(t, RIL_E_SUCCESS, sw_version, sizeof(sw_version));
167         ril_state.tokens.baseband_version = 0;
168 }
169
170 /**
171  * In: RIL_REQUEST_GET_IMSI
172  *   Get the SIM IMSI
173  *   Only valid when radio state is "RADIO_STATE_SIM_READY"
174  *
175  * Out: IPC_MISC_ME_IMSI
176  *   Requests ME's IMSI
177  */
178 void ril_request_get_imsi(RIL_Token t)
179 {
180         ipc_fmt_send_get(IPC_MISC_ME_IMSI, reqGetId(t));
181 }
182
183 /**
184  * In: IPC_MISC_ME_IMSI
185  *   Provides ME's IMSI
186  *
187  * Out: RIL_REQUEST_GET_IMSI
188  *   Get the SIM IMSI
189  *   Only valid when radio state is "RADIO_STATE_SIM_READY"
190  */
191 void ipc_misc_me_imsi(struct ipc_message_info *info)
192 {
193         unsigned char *imsi_length;
194         char *imsi;
195
196         if(info->length < 1) {
197                 LOGE("%s: zero data length", __FUNCTION__);
198                 RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
199                 return;
200         }
201
202         imsi_length = (unsigned char*) info->data;
203
204         if(((int) info->length) < *imsi_length + 1) {
205                 LOGE("%s: missing IMSI data", __FUNCTION__);
206                 RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_GENERIC_FAILURE, NULL, 0);
207                 return;
208         }
209
210         /* Copy IMSI */
211         imsi = (char*) malloc(*imsi_length+1);
212         memcpy(imsi, ((unsigned char*) info->data) + 1, *imsi_length);
213         imsi[*imsi_length] = '\0';
214
215         RIL_onRequestComplete(reqGetToken(info->aseq), RIL_E_SUCCESS, imsi, *imsi_length+1);
216 }
217
218 void ipc_misc_time_info(struct ipc_message_info *info)
219 {
220         struct ipc_misc_time_info *nitz = (struct ipc_misc_time_info*) info->data;
221         char str[128];
222
223         sprintf(str, "%02u/%02u/%02u,%02u:%02u:%02u+%02d,%02d",
224                 nitz->year, nitz->mon, nitz->day, nitz->hour, nitz->min, nitz->sec, nitz->tz, 0);
225
226         RIL_onUnsolicitedResponse(RIL_UNSOL_NITZ_TIME_RECEIVED, str, strlen(str) + 1);
227 }