Global include path
[libsamsung-ipc.git] / samsung-ipc / ipc_utils.c
1 /*
2  * This file is part of libsamsung-ipc.
3  *
4  * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com>
5  * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
6  *
7  * libsamsung-ipc 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 2 of the License, or
10  * (at your option) any later version.
11  *
12  * libsamsung-ipc 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 libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <string.h>
25 #include <fcntl.h>
26 #include <ctype.h>
27 #include <sys/ioctl.h>
28 #include <sys/stat.h>
29 #include <sys/types.h>
30 #include <asm/types.h>
31
32 #include <samsung-ipc.h>
33 #include <ipc.h>
34
35 const char *ipc_request_type_string(unsigned char type)
36 {
37     static char type_string[5] = { 0 };
38
39     switch (type) {
40         case IPC_TYPE_EXEC:
41             return "IPC_TYPE_EXEC";
42         case IPC_TYPE_GET:
43             return "IPC_TYPE_GET";
44         case IPC_TYPE_SET:
45             return "IPC_TYPE_SET";
46         case IPC_TYPE_CFRM:
47             return "IPC_TYPE_CFRM";
48         case IPC_TYPE_EVENT:
49             return "IPC_TYPE_EVENT";
50         default:
51             snprintf((char *) &type_string, sizeof(type_string), "0x%02x", type);
52             return type_string;
53     }
54 }
55
56 const char *ipc_response_type_string(unsigned char type)
57 {
58     static char type_string[5] = { 0 };
59
60     switch (type) {
61         case IPC_TYPE_INDI:
62             return "IPC_TYPE_INDI";
63         case IPC_TYPE_RESP:
64             return "IPC_TYPE_RESP";
65         case IPC_TYPE_NOTI:
66             return "IPC_TYPE_NOTI";
67         default:
68             snprintf((char *) &type_string, sizeof(type_string), "0x%02x", type);
69             return type_string;
70     }
71 }
72
73 const char *ipc_command_string(unsigned short command)
74 {
75     static char command_string[7] = { 0 };
76
77     switch (command) {
78         case IPC_PWR_PHONE_PWR_UP:
79             return "IPC_PWR_PHONE_PWR_UP";
80         case IPC_PWR_PHONE_PWR_OFF:
81             return "IPC_PWR_PHONE_PWR_OFF";
82         case IPC_PWR_PHONE_RESET:
83             return "IPC_PWR_PHONE_RESET";
84         case IPC_PWR_BATT_STATUS:
85             return "IPC_PWR_BATT_STATUS";
86         case IPC_PWR_BATT_TYPE:
87             return "IPC_PWR_BATT_TYPE";
88         case IPC_PWR_BATT_COMP:
89             return "IPC_PWR_BATT_COMP";
90         case IPC_PWR_PHONE_STATE:
91             return "IPC_PWR_PHONE_STATE";
92         case IPC_CALL_OUTGOING:
93             return "IPC_CALL_OUTGOING";
94         case IPC_CALL_INCOMING:
95             return "IPC_CALL_INCOMING";
96         case IPC_CALL_RELEASE:
97             return "IPC_CALL_RELEASE";
98         case IPC_CALL_ANSWER:
99             return "IPC_CALL_ANSWER";
100         case IPC_CALL_STATUS:
101             return "IPC_CALL_STATUS";
102         case IPC_CALL_LIST:
103             return "IPC_CALL_LIST";
104         case IPC_CALL_BURST_DTMF:
105             return "IPC_CALL_BURST_DTMF";
106         case IPC_CALL_CONT_DTMF:
107             return "IPC_CALL_CONT_DTMF";
108         case IPC_CALL_WAITING:
109             return "IPC_CALL_WAITING";
110         case IPC_CALL_LINE_ID:
111             return "IPC_CALL_LINE_ID";
112         case IPC_SMS_SEND_MSG:
113             return "IPC_SMS_SEND_MSG";
114         case IPC_SMS_INCOMING_MSG:
115             return "IPC_SMS_INCOMING_MSG";
116         case IPC_SMS_READ_MSG:
117             return "IPC_SMS_READ_MSG";
118         case IPC_SMS_SAVE_MSG:
119             return "IPC_SMS_SAVE_MSG";
120         case IPC_SMS_DEL_MSG:
121             return "IPC_SMS_DEL_MSG";
122         case IPC_SMS_DELIVER_REPORT:
123             return "IPC_SMS_DELIVER_REPORT";
124         case IPC_SMS_DEVICE_READY:
125             return "IPC_SMS_DEVICE_READY";
126         case IPC_SMS_SEL_MEM:
127             return "IPC_SMS_SEL_MEM";
128         case IPC_SMS_STORED_MSG_COUNT:
129             return "IPC_SMS_STORED_MSG_COUNT";
130         case IPC_SMS_SVC_CENTER_ADDR:
131             return "IPC_SMS_SVC_CENTER_ADDR";
132         case IPC_SMS_SVC_OPTION:
133             return "IPC_SMS_SVC_OPTION";
134         case IPC_SMS_MEM_STATUS:
135             return "IPC_SMS_MEM_STATUS";
136         case IPC_SMS_CBS_MSG:
137             return "IPC_SMS_CBS_MSG";
138         case IPC_SMS_CBS_CFG:
139             return "IPC_SMS_CBS_CFG";
140         case IPC_SMS_STORED_MSG_STATUS:
141             return "IPC_SMS_STORED_MSG_STATUS";
142         case IPC_SMS_PARAM_COUNT:
143             return "IPC_SMS_PARAM_COUNT";
144         case IPC_SMS_PARAM:
145             return "IPC_SMS_PARAM";
146         case IPC_SEC_PIN_STATUS:
147             return "IPC_SEC_PIN_STATUS";
148         case IPC_SEC_PHONE_LOCK:
149             return "IPC_SEC_PHONE_LOCK";
150         case IPC_SEC_CHANGE_LOCKING_PW:
151             return "IPC_SEC_CHANGE_LOCKING_PW";
152         case IPC_SEC_SIM_LANG:
153             return "IPC_SEC_SIM_LANG";
154         case IPC_SEC_RSIM_ACCESS:
155             return "IPC_SEC_RSIM_ACCESS";
156         case IPC_SEC_GSIM_ACCESS:
157             return "IPC_SEC_GSIM_ACCESS";
158         case IPC_SEC_SIM_ICC_TYPE:
159             return "IPC_SEC_SIM_ICC_TYPE";
160         case IPC_SEC_LOCK_INFOMATION:
161             return "IPC_SEC_LOCK_INFOMATION";
162         case IPC_SEC_IMS_AUTH:
163             return "IPC_SEC_IMS_AUTH";
164         case IPC_PB_ACCESS:
165             return "IPC_PB_ACCESS";
166         case IPC_PB_STORAGE:
167             return "IPC_PB_STORAGE";
168         case IPC_PB_STORAGE_LIST:
169             return "IPC_PB_STORAGE_LIST";
170         case IPC_PB_ENTRY_INFO:
171             return "IPC_PB_ENTRY_INFO";
172         case IPC_PB_3GPB_CAPA:
173             return "IPC_PB_3GPB_CAPA";
174         case IPC_DISP_ICON_INFO:
175             return "IPC_DISP_ICON_INFO";
176         case IPC_DISP_HOMEZONE_INFO:
177             return "IPC_DISP_HOMEZONE_INFO";
178         case IPC_DISP_RSSI_INFO:
179             return "IPC_DISP_RSSI_INFO";
180         case IPC_NET_PREF_PLMN:
181             return "IPC_NET_PREF_PLMN";
182         case IPC_NET_PLMN_SEL:
183             return "IPC_NET_PLMN_SEL";
184         case IPC_NET_SERVING_NETWORK:
185             return "IPC_NET_SERVING_NETWORK";
186         case IPC_NET_PLMN_LIST:
187             return "IPC_NET_PLMN_LIST";
188         case IPC_NET_REGIST:
189             return "IPC_NET_REGIST";
190         case IPC_NET_SUBSCRIBER_NUM:
191             return "IPC_NET_SUBSCRIBER_NUM";
192         case IPC_NET_BAND_SEL:
193             return "IPC_NET_BAND_SEL";
194         case IPC_NET_SERVICE_DOMAIN_CONFIG:
195             return "IPC_NET_SERVICE_DOMAIN_CONFIG";
196         case IPC_NET_POWERON_ATTACH:
197             return "IPC_NET_POWERON_ATTACH";
198         case IPC_NET_MODE_SEL:
199             return "IPC_NET_MODE_SEL";
200         case IPC_NET_ACQ_ORDER:
201             return "IPC_NET_ACQ_ORDER";
202         case IPC_NET_IDENTITY:
203             return "IPC_NET_IDENTITY";
204         case IPC_NET_PREFERRED_NETWORK_INFO:
205             return "IPC_NET_PREFERRED_NETWORK_INFO";
206         case IPC_SND_SPKR_VOLUME_CTRL:
207             return "IPC_SND_SPKR_VOLUME_CTRL";
208         case IPC_SND_MIC_MUTE_CTRL:
209             return "IPC_SND_MIC_MUTE_CTRL";
210         case IPC_SND_AUDIO_PATH_CTRL:
211             return "IPC_SND_AUDIO_PATH_CTRL";
212         case IPC_SND_AUDIO_SOURCE_CTRL:
213             return "IPC_SND_AUDIO_SOURCE_CTRL";
214         case IPC_SND_LOOPBACK_CTRL:
215             return "IPC_SND_LOOPBACK_CTRL";
216         case IPC_SND_VOICE_RECORDING_CTRL:
217             return "IPC_SND_VOICE_RECORDING_CTRL";
218         case IPC_SND_VIDEO_CALL_CTRL:
219             return "IPC_SND_VIDEO_CALL_CTRL";
220         case IPC_SND_RINGBACK_TONE_CTRL:
221             return "IPC_SND_RINGBACK_TONE_CTRL";
222         case IPC_SND_CLOCK_CTRL:
223             return "IPC_SND_CLOCK_CTRL";
224         case IPC_SND_WB_AMR_STATUS:
225             return "IPC_SND_WB_AMR_STATUS";
226         case IPC_MISC_ME_VERSION:
227             return "IPC_MISC_ME_VERSION";
228         case IPC_MISC_ME_IMSI:
229             return "IPC_MISC_ME_IMSI";
230         case IPC_MISC_ME_SN:
231             return "IPC_MISC_ME_SN";
232         case IPC_MISC_TIME_INFO:
233             return "IPC_MISC_TIME_INFO";
234         case IPC_MISC_DEBUG_LEVEL:
235             return "IPC_MISC_DEBUG_LEVEL";
236         case IPC_SVC_ENTER:
237             return "IPC_SVC_ENTER";
238         case IPC_SVC_END:
239             return "IPC_SVC_END";
240         case IPC_SVC_PRO_KEYCODE:
241             return "IPC_SVC_PRO_KEYCODE";
242         case IPC_SVC_SCREEN_CFG:
243             return "IPC_SVC_SCREEN_CFG";
244         case IPC_SVC_DISPLAY_SCREEN:
245             return "IPC_SVC_DISPLAY_SCREEN";
246         case IPC_SVC_CHANGE_SVC_MODE:
247             return "IPC_SVC_CHANGE_SVC_MODE";
248         case IPC_SVC_DEVICE_TEST:
249             return "IPC_SVC_DEVICE_TEST";
250         case IPC_SVC_DEBUG_DUMP:
251             return "IPC_SVC_DEBUG_DUMP";
252         case IPC_SVC_DEBUG_STRING:
253             return "IPC_SVC_DEBUG_STRING";
254         case IPC_SS_WAITING:
255             return "IPC_SS_WAITING";
256         case IPC_SS_CLI:
257             return "IPC_SS_CLI";
258         case IPC_SS_BARRING:
259             return "IPC_SS_BARRING";
260         case IPC_SS_BARRING_PW:
261             return "IPC_SS_BARRING_PW";
262         case IPC_SS_FORWARDING:
263             return "IPC_SS_FORWARDING";
264         case IPC_SS_INFO:
265             return "IPC_SS_INFO";
266         case IPC_SS_MANAGE_CALL:
267             return "IPC_SS_MANAGE_CALL";
268         case IPC_SS_USSD:
269             return "IPC_SS_USSD";
270         case IPC_SS_AOC:
271             return "IPC_SS_AOC";
272         case IPC_SS_RELEASE_COMPLETE:
273             return "IPC_SS_RELEASE_COMPLETE";
274         case IPC_GPRS_DEFINE_PDP_CONTEXT:
275             return "IPC_GPRS_DEFINE_PDP_CONTEXT";
276         case IPC_GPRS_QOS:
277             return "IPC_GPRS_QOS";
278         case IPC_GPRS_PS:
279             return "IPC_GPRS_PS";
280         case IPC_GPRS_PDP_CONTEXT:
281             return "IPC_GPRS_PDP_CONTEXT";
282         case IPC_GPRS_ENTER_DATA:
283             return "IPC_GPRS_ENTER_DATA";
284         case IPC_GPRS_SHOW_PDP_ADDR:
285             return "IPC_GPRS_SHOW_PDP_ADDR";
286         case IPC_GPRS_MS_CLASS:
287             return "IPC_GPRS_MS_CLASS";
288         case IPC_GPRS_3G_QUAL_SRVC_PROFILE:
289             return "IPC_GPRS_3G_QUAL_SRVC_PROFILE";
290         case IPC_GPRS_IP_CONFIGURATION:
291             return "IPC_GPRS_IP_CONFIGURATION";
292         case IPC_GPRS_DEFINE_SEC_PDP_CONTEXT:
293             return "IPC_GPRS_DEFINE_SEC_PDP_CONTEXT";
294         case IPC_GPRS_TFT:
295             return "IPC_GPRS_TFT";
296         case IPC_GPRS_HSDPA_STATUS:
297             return "IPC_GPRS_HSDPA_STATUS";
298         case IPC_GPRS_CURRENT_SESSION_DATA_COUNTER:
299             return "IPC_GPRS_CURRENT_SESSION_DATA_COUNTER";
300         case IPC_GPRS_DATA_DORMANT:
301             return "IPC_GPRS_DATA_DORMANT";
302         case IPC_GPRS_PIN_CTRL:
303             return "IPC_GPRS_PIN_CTRL";
304         case IPC_GPRS_CALL_STATUS:
305             return "IPC_GPRS_CALL_STATUS";
306         case IPC_GPRS_PORT_LIST:
307             return "IPC_GPRS_PORT_LIST";
308         case IPC_SAT_PROFILE_DOWNLOAD:
309             return "IPC_SAT_PROFILE_DOWNLOAD";
310         case IPC_SAT_ENVELOPE_CMD:
311             return "IPC_SAT_ENVELOPE_CMD";
312         case IPC_SAT_PROACTIVE_CMD:
313             return "IPC_SAT_PROACTIVE_CMD";
314         case IPC_SAT_TERMINATE_USAT_SESSION:
315             return "IPC_SAT_TERMINATE_USAT_SESSION";
316         case IPC_SAT_EVENT_DOWNLOAD:
317             return "IPC_SAT_EVENT_DOWNLOAD";
318         case IPC_SAT_PROVIDE_LOCAL_INFO:
319             return "IPC_SAT_PROVIDE_LOCAL_INFO";
320         case IPC_SAT_POLLING:
321             return "IPC_SAT_POLLING";
322         case IPC_SAT_REFRESH:
323             return "IPC_SAT_REFRESH";
324         case IPC_SAT_SETUP_EVENT_LIST:
325             return "IPC_SAT_SETUP_EVENT_LIST";
326         case IPC_SAT_CALL_CONTROL_RESULT:
327             return "IPC_SAT_CALL_CONTROL_RESULT";
328         case IPC_SAT_IMAGE_CLUT:
329             return "IPC_SAT_IMAGE_CLUT";
330         case IPC_SAT_SETUP_CALL_PROCESSING:
331             return "IPC_SAT_SETUP_CALL_PROCESSING";
332         case IPC_IMEI_START:
333             return "IPC_IMEI_START";
334         case IPC_IMEI_CHECK_DEVICE_INFO:
335             return "IPC_IMEI_CHECK_DEVICE_INFO";
336         case IPC_RFS_NV_READ_ITEM:
337             return "IPC_RFS_NV_READ_ITEM";
338         case IPC_RFS_NV_WRITE_ITEM:
339             return "IPC_RFS_NV_WRITE_ITEM";
340         case IPC_GEN_PHONE_RES:
341             return "IPC_GEN_PHONE_RES";
342         default:
343             snprintf((char *) &command_string, sizeof(command_string), "0x%04x", command);
344             return command_string;
345     }
346 }
347
348 void ipc_hex_dump(struct ipc_client *client, const void *data, size_t size)
349 {
350     /* dumps size bytes of *data to stdout. Looks like:
351      * [0000] 75 6E 6B 6E 6F 77 6E 20
352      *                  30 FF 00 00 00 00 39 00 unknown 0.....9.
353      * (in a single line of course)
354      */
355
356     unsigned char *p = (unsigned char *) data;
357     unsigned char c;
358     size_t n;
359     char bytestr[4] = {0};
360     char addrstr[10] = {0};
361     char hexstr[ 16*3 + 5] = {0};
362     char charstr[16*1 + 5] = {0};
363     for (n=1;n<=size;n++) {
364         if (n%16 == 1) {
365             /* store address for this line */
366             unsigned int end = 0, start = 0;
367             end = *((unsigned int*) p);
368             start = *((unsigned int*) data);
369             snprintf(addrstr, sizeof(addrstr), "%.4x", end - start);
370         }
371
372         c = *p;
373         if (isalnum(c) == 0) {
374             c = '.';
375         }
376
377         /* store hex str (for left side) */
378         snprintf(bytestr, sizeof(bytestr), "%02X ", *p);
379         strncat(hexstr, bytestr, sizeof(hexstr)-strlen(hexstr)-1);
380
381         /* store char str (for right side) */
382         snprintf(bytestr, sizeof(bytestr), "%c", c);
383         strncat(charstr, bytestr, sizeof(charstr)-strlen(charstr)-1);
384
385         if (n%16 == 0) {
386             /* line completed */
387             ipc_client_log(client, "[%4.4s]   %-50.50s  %s", addrstr, hexstr, charstr);
388             hexstr[0] = 0;
389             charstr[0] = 0;
390         } else if (n%8 == 0) {
391             /* half line: add whitespaces */
392             strncat(hexstr, "  ", sizeof(hexstr)-strlen(hexstr)-1);
393             strncat(charstr, " ", sizeof(charstr)-strlen(charstr)-1);
394         }
395         p++; /* next byte */
396     }
397
398     if (strlen(hexstr) > 0) {
399         /* print rest of buffer if not empty */
400         ipc_client_log(client, "[%4.4s]   %-50.50s  %s\n", addrstr, hexstr, charstr);
401     }
402 }
403
404 void ipc_client_log_send(struct ipc_client *client, struct ipc_message *message,
405     const char *prefix)
406 {
407     if (client == NULL || message == NULL || prefix == NULL)
408         return;
409
410     switch (client->type) {
411         case IPC_CLIENT_TYPE_FMT:
412             ipc_client_log(client, "%s: Sent FMT message", prefix);
413             ipc_client_log(client, "%s: Message: mseq=0x%02x, command=%s, type=%s, size=%d", prefix, message->mseq, ipc_command_string(message->command), ipc_request_type_string(message->type), message->size);
414 #ifdef DEBUG
415             if (message->size > 0) {
416                 ipc_client_log(client, "=============================== FMT data dump ================================");
417                 ipc_hex_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
418                 ipc_client_log(client, "==============================================================================");
419             }
420 #endif
421             break;
422         case IPC_CLIENT_TYPE_RFS:
423             ipc_client_log(client, "%s: Sent RFS message", prefix);
424             ipc_client_log(client, "%s: Message: mseq=0x%02x, command=%s, size=%d", prefix, message->mseq, ipc_command_string(message->command), message->size);
425 #ifdef DEBUG
426             if (message->size > 0) {
427                 ipc_client_log(client, "=============================== RFS data dump ================================");
428                 ipc_hex_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
429                 ipc_client_log(client, "==============================================================================");
430             }
431 #endif
432             break;
433     }
434 }
435
436 void ipc_client_log_recv(struct ipc_client *client, struct ipc_message *message,
437     const char *prefix)
438 {
439     if (client == NULL || message == NULL || prefix == NULL)
440         return;
441
442     switch (client->type) {
443         case IPC_CLIENT_TYPE_FMT:
444             ipc_client_log(client, "%s: Received FMT message", prefix);
445             ipc_client_log(client, "%s: Message: aseq=0x%02x, command=%s, type=%s, size=%d", prefix, message->aseq, ipc_command_string(message->command), ipc_response_type_string(message->type), message->size);
446 #ifdef DEBUG
447             if (message->size > 0) {
448                 ipc_client_log(client, "=============================== FMT data dump ================================");
449                 ipc_hex_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
450                 ipc_client_log(client, "==============================================================================");
451             }
452 #endif
453             break;
454         case IPC_CLIENT_TYPE_RFS:
455             ipc_client_log(client, "%s: Received RFS message", prefix);
456             ipc_client_log(client, "%s: Message: aseq=0x%02x, command=%s, size=%d", prefix, message->aseq, ipc_command_string(message->command), message->size);
457 #ifdef DEBUG
458             if (message->size > 0) {
459                 ipc_client_log(client, "=============================== RFS data dump ================================");
460                 ipc_hex_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
461                 ipc_client_log(client, "==============================================================================");
462             }
463 #endif
464             break;
465     }
466 }
467
468 int ipc_fmt_header_setup(struct ipc_fmt_header *header,
469     const struct ipc_message *message)
470 {
471     if (header == NULL || message == NULL)
472         return -1;
473
474     memset(header, 0, sizeof(struct ipc_fmt_header));
475     header->length = message->size + sizeof(struct ipc_fmt_header);
476     header->mseq = message->mseq;
477     header->aseq = message->aseq;
478     header->group = IPC_GROUP(message->command);
479     header->index = IPC_INDEX(message->command);
480     header->type = message->type;
481
482     return 0;
483 }
484
485 int ipc_fmt_message_setup(const struct ipc_fmt_header *header,
486     struct ipc_message *message)
487 {
488     if (header == NULL || message == NULL)
489         return -1;
490
491     memset(message, 0, sizeof(struct ipc_message));
492     message->mseq = header->mseq;
493     message->aseq = header->aseq;
494     message->command = IPC_COMMAND(header->group, header->index);
495     message->type = header->type;
496     message->data = NULL;
497     message->size = 0;
498
499     return 0;
500 }
501
502 int ipc_rfs_header_setup(struct ipc_rfs_header *header,
503     const struct ipc_message *message)
504 {
505     if (header == NULL || message == NULL)
506         return -1;
507
508     memset(header, 0, sizeof(struct ipc_rfs_header));
509     header->length = message->size + sizeof(struct ipc_rfs_header);
510     header->id = message->mseq;
511     header->index = IPC_INDEX(message->command);
512
513     return 0;
514 }
515
516 int ipc_rfs_message_setup(const struct ipc_rfs_header *header,
517     struct ipc_message *message)
518 {
519     if (header == NULL || message == NULL)
520         return -1;
521
522     memset(message, 0, sizeof(struct ipc_message));
523     message->aseq = header->id;
524     message->command = IPC_COMMAND(IPC_GROUP_RFS, header->index);
525     message->data = NULL;
526     message->size = 0;
527
528     return 0;
529 }
530
531 // vim:ts=4:sw=4:expandtab