ipc_utils: New line before printing I/O debug
[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 int ipc_seq_valid(unsigned char seq)
36 {
37     if (seq == 0x00 || seq == 0xff)
38         return 0;
39
40     return 1;
41 }
42
43 const char *ipc_request_type_string(unsigned char type)
44 {
45     static char type_string[5] = { 0 };
46
47     switch (type) {
48         case IPC_TYPE_EXEC:
49             return "IPC_TYPE_EXEC";
50         case IPC_TYPE_GET:
51             return "IPC_TYPE_GET";
52         case IPC_TYPE_SET:
53             return "IPC_TYPE_SET";
54         case IPC_TYPE_CFRM:
55             return "IPC_TYPE_CFRM";
56         case IPC_TYPE_EVENT:
57             return "IPC_TYPE_EVENT";
58         default:
59             snprintf((char *) &type_string, sizeof(type_string), "0x%02x", type);
60             return type_string;
61     }
62 }
63
64 const char *ipc_response_type_string(unsigned char type)
65 {
66     static char type_string[5] = { 0 };
67
68     switch (type) {
69         case IPC_TYPE_INDI:
70             return "IPC_TYPE_INDI";
71         case IPC_TYPE_RESP:
72             return "IPC_TYPE_RESP";
73         case IPC_TYPE_NOTI:
74             return "IPC_TYPE_NOTI";
75         default:
76             snprintf((char *) &type_string, sizeof(type_string), "0x%02x", type);
77             return type_string;
78     }
79 }
80
81 const char *ipc_command_string(unsigned short command)
82 {
83     static char command_string[7] = { 0 };
84
85     switch (command) {
86         case IPC_PWR_PHONE_PWR_UP:
87             return "IPC_PWR_PHONE_PWR_UP";
88         case IPC_PWR_PHONE_PWR_OFF:
89             return "IPC_PWR_PHONE_PWR_OFF";
90         case IPC_PWR_PHONE_RESET:
91             return "IPC_PWR_PHONE_RESET";
92         case IPC_PWR_BATT_STATUS:
93             return "IPC_PWR_BATT_STATUS";
94         case IPC_PWR_BATT_TYPE:
95             return "IPC_PWR_BATT_TYPE";
96         case IPC_PWR_BATT_COMP:
97             return "IPC_PWR_BATT_COMP";
98         case IPC_PWR_PHONE_STATE:
99             return "IPC_PWR_PHONE_STATE";
100         case IPC_CALL_OUTGOING:
101             return "IPC_CALL_OUTGOING";
102         case IPC_CALL_INCOMING:
103             return "IPC_CALL_INCOMING";
104         case IPC_CALL_RELEASE:
105             return "IPC_CALL_RELEASE";
106         case IPC_CALL_ANSWER:
107             return "IPC_CALL_ANSWER";
108         case IPC_CALL_STATUS:
109             return "IPC_CALL_STATUS";
110         case IPC_CALL_LIST:
111             return "IPC_CALL_LIST";
112         case IPC_CALL_BURST_DTMF:
113             return "IPC_CALL_BURST_DTMF";
114         case IPC_CALL_CONT_DTMF:
115             return "IPC_CALL_CONT_DTMF";
116         case IPC_CALL_WAITING:
117             return "IPC_CALL_WAITING";
118         case IPC_CALL_LINE_ID:
119             return "IPC_CALL_LINE_ID";
120         case IPC_SMS_SEND_MSG:
121             return "IPC_SMS_SEND_MSG";
122         case IPC_SMS_INCOMING_MSG:
123             return "IPC_SMS_INCOMING_MSG";
124         case IPC_SMS_READ_MSG:
125             return "IPC_SMS_READ_MSG";
126         case IPC_SMS_SAVE_MSG:
127             return "IPC_SMS_SAVE_MSG";
128         case IPC_SMS_DEL_MSG:
129             return "IPC_SMS_DEL_MSG";
130         case IPC_SMS_DELIVER_REPORT:
131             return "IPC_SMS_DELIVER_REPORT";
132         case IPC_SMS_DEVICE_READY:
133             return "IPC_SMS_DEVICE_READY";
134         case IPC_SMS_SEL_MEM:
135             return "IPC_SMS_SEL_MEM";
136         case IPC_SMS_STORED_MSG_COUNT:
137             return "IPC_SMS_STORED_MSG_COUNT";
138         case IPC_SMS_SVC_CENTER_ADDR:
139             return "IPC_SMS_SVC_CENTER_ADDR";
140         case IPC_SMS_SVC_OPTION:
141             return "IPC_SMS_SVC_OPTION";
142         case IPC_SMS_MEM_STATUS:
143             return "IPC_SMS_MEM_STATUS";
144         case IPC_SMS_CBS_MSG:
145             return "IPC_SMS_CBS_MSG";
146         case IPC_SMS_CBS_CFG:
147             return "IPC_SMS_CBS_CFG";
148         case IPC_SMS_STORED_MSG_STATUS:
149             return "IPC_SMS_STORED_MSG_STATUS";
150         case IPC_SMS_PARAM_COUNT:
151             return "IPC_SMS_PARAM_COUNT";
152         case IPC_SMS_PARAM:
153             return "IPC_SMS_PARAM";
154         case IPC_SEC_PIN_STATUS:
155             return "IPC_SEC_PIN_STATUS";
156         case IPC_SEC_PHONE_LOCK:
157             return "IPC_SEC_PHONE_LOCK";
158         case IPC_SEC_CHANGE_LOCKING_PW:
159             return "IPC_SEC_CHANGE_LOCKING_PW";
160         case IPC_SEC_SIM_LANG:
161             return "IPC_SEC_SIM_LANG";
162         case IPC_SEC_RSIM_ACCESS:
163             return "IPC_SEC_RSIM_ACCESS";
164         case IPC_SEC_GSIM_ACCESS:
165             return "IPC_SEC_GSIM_ACCESS";
166         case IPC_SEC_SIM_ICC_TYPE:
167             return "IPC_SEC_SIM_ICC_TYPE";
168         case IPC_SEC_LOCK_INFOMATION:
169             return "IPC_SEC_LOCK_INFOMATION";
170         case IPC_SEC_IMS_AUTH:
171             return "IPC_SEC_IMS_AUTH";
172         case IPC_PB_ACCESS:
173             return "IPC_PB_ACCESS";
174         case IPC_PB_STORAGE:
175             return "IPC_PB_STORAGE";
176         case IPC_PB_STORAGE_LIST:
177             return "IPC_PB_STORAGE_LIST";
178         case IPC_PB_ENTRY_INFO:
179             return "IPC_PB_ENTRY_INFO";
180         case IPC_PB_3GPB_CAPA:
181             return "IPC_PB_3GPB_CAPA";
182         case IPC_DISP_ICON_INFO:
183             return "IPC_DISP_ICON_INFO";
184         case IPC_DISP_HOMEZONE_INFO:
185             return "IPC_DISP_HOMEZONE_INFO";
186         case IPC_DISP_RSSI_INFO:
187             return "IPC_DISP_RSSI_INFO";
188         case IPC_NET_PREF_PLMN:
189             return "IPC_NET_PREF_PLMN";
190         case IPC_NET_PLMN_SEL:
191             return "IPC_NET_PLMN_SEL";
192         case IPC_NET_SERVING_NETWORK:
193             return "IPC_NET_SERVING_NETWORK";
194         case IPC_NET_PLMN_LIST:
195             return "IPC_NET_PLMN_LIST";
196         case IPC_NET_REGIST:
197             return "IPC_NET_REGIST";
198         case IPC_NET_SUBSCRIBER_NUM:
199             return "IPC_NET_SUBSCRIBER_NUM";
200         case IPC_NET_BAND_SEL:
201             return "IPC_NET_BAND_SEL";
202         case IPC_NET_SERVICE_DOMAIN_CONFIG:
203             return "IPC_NET_SERVICE_DOMAIN_CONFIG";
204         case IPC_NET_POWERON_ATTACH:
205             return "IPC_NET_POWERON_ATTACH";
206         case IPC_NET_MODE_SEL:
207             return "IPC_NET_MODE_SEL";
208         case IPC_NET_ACQ_ORDER:
209             return "IPC_NET_ACQ_ORDER";
210         case IPC_NET_IDENTITY:
211             return "IPC_NET_IDENTITY";
212         case IPC_NET_PREFERRED_NETWORK_INFO:
213             return "IPC_NET_PREFERRED_NETWORK_INFO";
214         case IPC_SND_SPKR_VOLUME_CTRL:
215             return "IPC_SND_SPKR_VOLUME_CTRL";
216         case IPC_SND_MIC_MUTE_CTRL:
217             return "IPC_SND_MIC_MUTE_CTRL";
218         case IPC_SND_AUDIO_PATH_CTRL:
219             return "IPC_SND_AUDIO_PATH_CTRL";
220         case IPC_SND_AUDIO_SOURCE_CTRL:
221             return "IPC_SND_AUDIO_SOURCE_CTRL";
222         case IPC_SND_LOOPBACK_CTRL:
223             return "IPC_SND_LOOPBACK_CTRL";
224         case IPC_SND_VOICE_RECORDING_CTRL:
225             return "IPC_SND_VOICE_RECORDING_CTRL";
226         case IPC_SND_VIDEO_CALL_CTRL:
227             return "IPC_SND_VIDEO_CALL_CTRL";
228         case IPC_SND_RINGBACK_TONE_CTRL:
229             return "IPC_SND_RINGBACK_TONE_CTRL";
230         case IPC_SND_CLOCK_CTRL:
231             return "IPC_SND_CLOCK_CTRL";
232         case IPC_SND_WB_AMR_STATUS:
233             return "IPC_SND_WB_AMR_STATUS";
234         case IPC_MISC_ME_VERSION:
235             return "IPC_MISC_ME_VERSION";
236         case IPC_MISC_ME_IMSI:
237             return "IPC_MISC_ME_IMSI";
238         case IPC_MISC_ME_SN:
239             return "IPC_MISC_ME_SN";
240         case IPC_MISC_TIME_INFO:
241             return "IPC_MISC_TIME_INFO";
242         case IPC_MISC_DEBUG_LEVEL:
243             return "IPC_MISC_DEBUG_LEVEL";
244         case IPC_SVC_ENTER:
245             return "IPC_SVC_ENTER";
246         case IPC_SVC_END:
247             return "IPC_SVC_END";
248         case IPC_SVC_PRO_KEYCODE:
249             return "IPC_SVC_PRO_KEYCODE";
250         case IPC_SVC_SCREEN_CFG:
251             return "IPC_SVC_SCREEN_CFG";
252         case IPC_SVC_DISPLAY_SCREEN:
253             return "IPC_SVC_DISPLAY_SCREEN";
254         case IPC_SVC_CHANGE_SVC_MODE:
255             return "IPC_SVC_CHANGE_SVC_MODE";
256         case IPC_SVC_DEVICE_TEST:
257             return "IPC_SVC_DEVICE_TEST";
258         case IPC_SVC_DEBUG_DUMP:
259             return "IPC_SVC_DEBUG_DUMP";
260         case IPC_SVC_DEBUG_STRING:
261             return "IPC_SVC_DEBUG_STRING";
262         case IPC_SS_WAITING:
263             return "IPC_SS_WAITING";
264         case IPC_SS_CLI:
265             return "IPC_SS_CLI";
266         case IPC_SS_BARRING:
267             return "IPC_SS_BARRING";
268         case IPC_SS_BARRING_PW:
269             return "IPC_SS_BARRING_PW";
270         case IPC_SS_FORWARDING:
271             return "IPC_SS_FORWARDING";
272         case IPC_SS_INFO:
273             return "IPC_SS_INFO";
274         case IPC_SS_MANAGE_CALL:
275             return "IPC_SS_MANAGE_CALL";
276         case IPC_SS_USSD:
277             return "IPC_SS_USSD";
278         case IPC_SS_AOC:
279             return "IPC_SS_AOC";
280         case IPC_SS_RELEASE_COMPLETE:
281             return "IPC_SS_RELEASE_COMPLETE";
282         case IPC_GPRS_DEFINE_PDP_CONTEXT:
283             return "IPC_GPRS_DEFINE_PDP_CONTEXT";
284         case IPC_GPRS_QOS:
285             return "IPC_GPRS_QOS";
286         case IPC_GPRS_PS:
287             return "IPC_GPRS_PS";
288         case IPC_GPRS_PDP_CONTEXT:
289             return "IPC_GPRS_PDP_CONTEXT";
290         case IPC_GPRS_ENTER_DATA:
291             return "IPC_GPRS_ENTER_DATA";
292         case IPC_GPRS_SHOW_PDP_ADDR:
293             return "IPC_GPRS_SHOW_PDP_ADDR";
294         case IPC_GPRS_MS_CLASS:
295             return "IPC_GPRS_MS_CLASS";
296         case IPC_GPRS_3G_QUAL_SRVC_PROFILE:
297             return "IPC_GPRS_3G_QUAL_SRVC_PROFILE";
298         case IPC_GPRS_IP_CONFIGURATION:
299             return "IPC_GPRS_IP_CONFIGURATION";
300         case IPC_GPRS_DEFINE_SEC_PDP_CONTEXT:
301             return "IPC_GPRS_DEFINE_SEC_PDP_CONTEXT";
302         case IPC_GPRS_TFT:
303             return "IPC_GPRS_TFT";
304         case IPC_GPRS_HSDPA_STATUS:
305             return "IPC_GPRS_HSDPA_STATUS";
306         case IPC_GPRS_CURRENT_SESSION_DATA_COUNTER:
307             return "IPC_GPRS_CURRENT_SESSION_DATA_COUNTER";
308         case IPC_GPRS_DATA_DORMANT:
309             return "IPC_GPRS_DATA_DORMANT";
310         case IPC_GPRS_PIN_CTRL:
311             return "IPC_GPRS_PIN_CTRL";
312         case IPC_GPRS_CALL_STATUS:
313             return "IPC_GPRS_CALL_STATUS";
314         case IPC_GPRS_PORT_LIST:
315             return "IPC_GPRS_PORT_LIST";
316         case IPC_SAT_PROFILE_DOWNLOAD:
317             return "IPC_SAT_PROFILE_DOWNLOAD";
318         case IPC_SAT_ENVELOPE_CMD:
319             return "IPC_SAT_ENVELOPE_CMD";
320         case IPC_SAT_PROACTIVE_CMD:
321             return "IPC_SAT_PROACTIVE_CMD";
322         case IPC_SAT_TERMINATE_USAT_SESSION:
323             return "IPC_SAT_TERMINATE_USAT_SESSION";
324         case IPC_SAT_EVENT_DOWNLOAD:
325             return "IPC_SAT_EVENT_DOWNLOAD";
326         case IPC_SAT_PROVIDE_LOCAL_INFO:
327             return "IPC_SAT_PROVIDE_LOCAL_INFO";
328         case IPC_SAT_POLLING:
329             return "IPC_SAT_POLLING";
330         case IPC_SAT_REFRESH:
331             return "IPC_SAT_REFRESH";
332         case IPC_SAT_SETUP_EVENT_LIST:
333             return "IPC_SAT_SETUP_EVENT_LIST";
334         case IPC_SAT_CALL_CONTROL_RESULT:
335             return "IPC_SAT_CALL_CONTROL_RESULT";
336         case IPC_SAT_IMAGE_CLUT:
337             return "IPC_SAT_IMAGE_CLUT";
338         case IPC_SAT_SETUP_CALL_PROCESSING:
339             return "IPC_SAT_SETUP_CALL_PROCESSING";
340         case IPC_IMEI_START:
341             return "IPC_IMEI_START";
342         case IPC_IMEI_CHECK_DEVICE_INFO:
343             return "IPC_IMEI_CHECK_DEVICE_INFO";
344         case IPC_RFS_NV_READ_ITEM:
345             return "IPC_RFS_NV_READ_ITEM";
346         case IPC_RFS_NV_WRITE_ITEM:
347             return "IPC_RFS_NV_WRITE_ITEM";
348         case IPC_GEN_PHONE_RES:
349             return "IPC_GEN_PHONE_RES";
350         default:
351             snprintf((char *) &command_string, sizeof(command_string), "0x%04x", command);
352             return command_string;
353     }
354 }
355
356 int ipc_data_dump(struct ipc_client *client, const void *data, size_t size)
357 {
358     unsigned int cols = 8;
359     unsigned int cols_count = 2;
360     int spacer;
361     char string[81];
362     size_t length;
363     char *print;
364     unsigned char *p;
365     unsigned int offset;
366     unsigned int rollback;
367     unsigned int i, j, k;
368     int rc;
369
370     if (data == NULL || size == 0)
371         return -1;
372
373     // spacer = string length - offset print length - data print length - ascii print length
374     spacer = (sizeof(string) - 1) - 6 - (3 * cols * cols_count - 1 + (cols_count - 1)) - (cols * cols_count + cols_count - 1);
375
376     // Need 3 spacers
377     spacer /= 3;
378
379     if (spacer <= 0)
380         return -1;
381
382     p = (unsigned char *) data;
383     offset = 0;
384
385     while (offset < size) {
386         rollback = 0;
387
388         print = (char *) &string;
389         length = sizeof(string);
390
391         // Offset print
392
393         rc = snprintf(print, length, "[%04x]", offset);
394         print += rc;
395         length -= rc;
396
397         // Spacer print
398
399         for (i = 0; i < (unsigned int) spacer; i++) {
400             *print++ = ' ';
401             length--;
402         }
403
404         // Data print
405
406         for (i = 0; i < cols_count; i++) {
407             for (j = 0; j < cols; j++) {
408                 if (offset < size) {
409                     rc = snprintf(print, length, "%02X", *p);
410                     print += rc;
411                     length -= rc;
412
413                     p++;
414                     offset++;
415                     rollback++;
416                 } else {
417                     for (k = 0; k < 2; k++) {
418                         *print++ = ' ';
419                         length--;
420                     }
421                 }
422
423                 if (j != (cols - 1)) {
424                     *print++ = ' ';
425                     length--;
426                 }
427             }
428
429             if (i != (cols_count - 1)) {
430                 for (k = 0; k < 2; k++) {
431                     *print++ = ' ';
432                     length--;
433                 }
434             }
435         }
436
437         // Spacer print
438
439         for (i = 0; i < (unsigned int) spacer; i++) {
440             *print++ = ' ';
441             length--;
442         }
443
444         // ASCII print
445
446         p -= rollback;
447         offset -= rollback;
448
449         for (i = 0; i < cols_count; i++) {
450             for (j = 0; j < cols; j++) {
451                 if (offset < size) {
452                     if (isascii(*p) && isprint(*p))
453                         *print = *p;
454                     else
455                         *print = '.';
456
457                     print++;
458                     length--;
459
460                     p++;
461                     offset++;
462                     rollback++;
463                 }
464             }
465
466             if (i != (cols_count - 1) && offset < size) {
467                 *print++ = ' ';
468                 length--;
469             }
470         }
471
472         *print = '\0';
473
474         ipc_client_log(client, string);
475     }
476
477     return 0;
478 }
479
480 void ipc_client_log_send(struct ipc_client *client, struct ipc_message *message,
481     const char *prefix)
482 {
483     if (client == NULL || message == NULL || prefix == NULL)
484         return;
485
486     switch (client->type) {
487         case IPC_CLIENT_TYPE_FMT:
488             ipc_client_log(client, "\n");
489             ipc_client_log(client, "%s: Sent FMT message", prefix);
490             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);
491 #ifdef DEBUG
492             if (message->size > 0) {
493                 ipc_client_log(client, "================================= IPC FMT data =================================");
494                 ipc_data_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
495                 ipc_client_log(client, "================================================================================");
496             }
497 #endif
498             break;
499         case IPC_CLIENT_TYPE_RFS:
500             ipc_client_log(client, "\n");
501             ipc_client_log(client, "%s: Sent RFS message", prefix);
502             ipc_client_log(client, "%s: Message: mseq=0x%02x, command=%s, size=%d", prefix, message->mseq, ipc_command_string(message->command), message->size);
503 #ifdef DEBUG
504             if (message->size > 0) {
505                 ipc_client_log(client, "================================= IPC RFS data =================================");
506                 ipc_data_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
507                 ipc_client_log(client, "================================================================================");
508             }
509 #endif
510             break;
511     }
512 }
513
514 void ipc_client_log_recv(struct ipc_client *client, struct ipc_message *message,
515     const char *prefix)
516 {
517     if (client == NULL || message == NULL || prefix == NULL)
518         return;
519
520     switch (client->type) {
521         case IPC_CLIENT_TYPE_FMT:
522             ipc_client_log(client, "\n");
523             ipc_client_log(client, "%s: Received FMT message", prefix);
524             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);
525 #ifdef DEBUG
526             if (message->size > 0) {
527                 ipc_client_log(client, "================================= IPC FMT data =================================");
528                 ipc_data_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
529                 ipc_client_log(client, "================================================================================");
530             }
531 #endif
532             break;
533         case IPC_CLIENT_TYPE_RFS:
534             ipc_client_log(client, "\n");
535             ipc_client_log(client, "%s: Received RFS message", prefix);
536             ipc_client_log(client, "%s: Message: aseq=0x%02x, command=%s, size=%d", prefix, message->aseq, ipc_command_string(message->command), message->size);
537 #ifdef DEBUG
538             if (message->size > 0) {
539                 ipc_client_log(client, "================================= IPC RFS data =================================");
540                 ipc_data_dump(client, (void *) message->data, message->size > 0x100 ? 0x100 : message->size);
541                 ipc_client_log(client, "================================================================================");
542             }
543 #endif
544             break;
545     }
546 }
547
548 int ipc_fmt_header_setup(struct ipc_fmt_header *header,
549     const struct ipc_message *message)
550 {
551     if (header == NULL || message == NULL)
552         return -1;
553
554     memset(header, 0, sizeof(struct ipc_fmt_header));
555     header->length = message->size + sizeof(struct ipc_fmt_header);
556     header->mseq = message->mseq;
557     header->aseq = message->aseq;
558     header->group = IPC_GROUP(message->command);
559     header->index = IPC_INDEX(message->command);
560     header->type = message->type;
561
562     return 0;
563 }
564
565 int ipc_fmt_message_setup(const struct ipc_fmt_header *header,
566     struct ipc_message *message)
567 {
568     if (header == NULL || message == NULL)
569         return -1;
570
571     memset(message, 0, sizeof(struct ipc_message));
572     message->mseq = header->mseq;
573     message->aseq = header->aseq;
574     message->command = IPC_COMMAND(header->group, header->index);
575     message->type = header->type;
576     message->data = NULL;
577     message->size = 0;
578
579     return 0;
580 }
581
582 int ipc_rfs_header_setup(struct ipc_rfs_header *header,
583     const struct ipc_message *message)
584 {
585     if (header == NULL || message == NULL)
586         return -1;
587
588     memset(header, 0, sizeof(struct ipc_rfs_header));
589     header->length = message->size + sizeof(struct ipc_rfs_header);
590     header->id = message->mseq;
591     header->index = IPC_INDEX(message->command);
592
593     return 0;
594 }
595
596 int ipc_rfs_message_setup(const struct ipc_rfs_header *header,
597     struct ipc_message *message)
598 {
599     if (header == NULL || message == NULL)
600         return -1;
601
602     memset(message, 0, sizeof(struct ipc_message));
603     message->aseq = header->id;
604     message->command = IPC_COMMAND(IPC_GROUP_RFS, header->index);
605     message->data = NULL;
606     message->size = 0;
607
608     return 0;
609 }
610
611 // vim:ts=4:sw=4:expandtab