3a11a4af272c70ab1728eda3da4f32d4c30d2f12
[profile/ivi/ico-uxf-homescreen.git] / apps_controller / ico_syc_apc_regulation.c
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9 /**
10  * @brief   Regulation controller
11  *
12  * @date    Feb-28-2013
13  */
14
15 #include    <stdio.h>
16 #include    <stdlib.h>
17 #include    <unistd.h>
18 #include    <stdbool.h>
19 #include    <string.h>
20 #include    <errno.h>
21 #include    <pthread.h>
22 #include    <sys/ioctl.h>
23 #include    <sys/time.h>
24 #include    <fcntl.h>
25
26 #include    <wayland-client.h>
27 #include    <ico_window_mgr-client-protocol.h>
28 #include    <dbus/dbus.h>
29 #include    <Ecore.h>
30 #include    "ico_apf.h"
31 #include    "ico_uxf.h"
32 #include    "ico_syc_apc.h"
33 #include    "ico_syc_apc_private.h"
34
35 /*==============================================================================*/
36 /* static tables                                                                */
37 /*==============================================================================*/
38 /* callback function            */
39 static int  nregulation_cb = 0;
40 static ico_apc_regulation_cb_t  regulation_cb[ICO_SYC_APC_REGULATION_LISTENERS];
41 static void                     *regulation_cb_user_data[ICO_SYC_APC_REGULATION_LISTENERS];
42
43 /* Ecore/D-Bus static valiables */
44 static Ecore_Timer *vehicle_timer = NULL;
45 static DBusConnection *dbus_connection = NULL;
46 static ico_apc_reguration_control_t control[ICO_UXF_CATEGORY_MAX];
47
48 /* vehicle information          */
49 static const struct _vehicle_info_property {
50     int     key;                        /* Vehicle Information key                  */
51     char    *property;                  /* D-Bus property name                      */
52     char    *path;                      /* D-Bus path name                          */
53     char    *interface;                 /* D-Bus interface name                     */
54 }                   vehicle_info[] = {
55     { ICO_SYC_VEHICLEINFO_VEHICLE_SPEED, "VehicleSpeed",
56       "/org/automotive/runningstatus/vehicleSpeed", "org.automotive.vehicleSpeed" },
57     { ICO_SYC_VEHICLEINFO_SHIFT_POSITION, "ShiftPosition",
58       "/org/automotive/runningstatus/transmission", "org.automotive.transmission" },
59 #if 0   /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
60     { ICO_SYC_VEHICLEINFO_TURN_SIGNAL, "TurnSignal",
61       "/org/automotive/runningstatus/turnSignal", "org.automotive.turnSignal" },
62 #else   /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
63     { ICO_SYC_VEHICLEINFO_LIGHT_LEFT, "LeftTurn",
64       "/org/automotive/runningstatus/lightStatus", "org.automotive.lightStatus" },
65     { ICO_SYC_VEHICLEINFO_LIGHT_RIGHT, "RightTurn",
66       "/org/automotive/runningstatus/lightStatus", "org.automotive.lightStatus" },
67 #endif  /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
68     { 0, "\0", "\0", "\0" }
69 };
70
71 /* Vehicle information data     */
72 static struct _vehicle_info_data    {
73     int             key;                /* Vehicle Information key                  */
74     DBusPendingCall *pending;
75     int             request;
76     int             errcount;
77     double          val;
78 }                   vehicle_data[ICO_UXF_REGULATION_VIC_MAX];
79
80 /* system configuration         */
81 static Ico_Uxf_Sys_Config       *confsys = NULL;
82 static int      ncategory;
83 static Ico_Uxf_conf_category    *category;
84
85 /*==============================================================================*/
86 /* define static function prototype                                             */
87 /*==============================================================================*/
88 static int request_vehicle_info(void);
89 static int get_vehicle_info(void);
90 static Eina_Bool rule_engine_wake(void *user_data);
91
92 /*--------------------------------------------------------------------------*/
93 /**
94  * @brief   request_vehicle_info: request to AMB(static function)
95  *
96  * @param       none
97  * @return      result
98  * @retval      ICO_SYC_EOK     success
99  * @retval      ICO_SYC_EIO     error(D-Bus send error)
100  */
101 /*--------------------------------------------------------------------------*/
102 static int
103 request_vehicle_info(void)
104 {
105     DBusMessage *dbus_message = NULL;
106     int     idx;
107     int     ret = ICO_SYC_EOK;
108
109     for (idx = 0; vehicle_info[idx].key; idx++) {
110
111         /* set vehicle info key     */
112         vehicle_data[idx].key = vehicle_info[idx].key;
113
114         if (vehicle_data[idx].pending)  {
115             continue;
116         }
117
118         if (vehicle_info[idx].path[0] == 0) {
119             /* currently not support this vehicle information   */
120             continue;
121         }
122
123         /* Create send message      */
124         dbus_message = dbus_message_new_method_call(DBUS_SERVICE, vehicle_info[idx].path,
125                                                     DBUS_INTERFACE, DBUS_METHOD);
126         if (! dbus_message) {
127             apfw_warn("request_vehicle_info: ERROR dbus_message_new_method_call" );
128             ret = ICO_SYC_EIO;
129         }
130         /* Set parameters into message  */
131         else if (! dbus_message_append_args(
132                             dbus_message,
133                             DBUS_TYPE_STRING, &vehicle_info[idx].interface,
134                             DBUS_TYPE_STRING, &vehicle_info[idx].property,
135                             DBUS_TYPE_INVALID)) {
136             apfw_warn("request_vehicle_info: ERROR dbus_message_append_args" );
137             ret = ICO_SYC_EIO;
138         }
139         /* Set destination              */
140         else if (! dbus_message_set_destination(dbus_message, DBUS_SERVICE))    {
141             apfw_warn("request_vehicle_info: ERROR dbus_message_set_destination" );
142             ret = ICO_SYC_EIO;
143         }
144         /* Send message                 */
145         else if (! dbus_connection_send_with_reply(
146                             dbus_connection, dbus_message,
147                             &vehicle_data[idx].pending, 200))    {
148             apfw_warn("request_vehicle_info: ERROR dbus_connection_send" );
149             vehicle_data[idx].pending = NULL;
150             ret = ICO_SYC_EIO;
151         }
152         if (dbus_message)   {
153             /* Release message                  */
154             dbus_message_unref(dbus_message);
155         }
156     }
157
158     /* dispatch if data queue exist         */
159     do  {
160         dbus_connection_read_write_dispatch(dbus_connection, 0);
161     } while (dbus_connection_get_dispatch_status(dbus_connection)
162              == DBUS_DISPATCH_DATA_REMAINS);
163
164     return(ret);
165 }
166
167 /*--------------------------------------------------------------------------*/
168 /**
169  * @brief   get_vehicle_info: get vercle information from AMB(static function)
170  *
171  * @param       none
172  * @return      always ICO_SYC_EOK(success)
173  */
174 /*--------------------------------------------------------------------------*/
175 static int
176 get_vehicle_info(void)
177 {
178     DBusMessage *dbus_message = NULL;
179     DBusMessageIter iter_head;
180     DBusMessageIter iter;
181     int         idx;
182     char        type;
183     int32_t     i32;
184     int16_t     i16;
185     uint32_t    u32;
186     uint16_t    u16;
187     dbus_bool_t b;
188     uint8_t     u8;
189     double      d64;
190
191     /* dispatch if data queue exist         */
192     do {
193         dbus_connection_read_write_dispatch(dbus_connection, 0);
194     } while (dbus_connection_get_dispatch_status(dbus_connection)
195              == DBUS_DISPATCH_DATA_REMAINS);
196
197     /* analize reply datas                  */
198     for (idx = 0; vehicle_info[idx].key; idx++) {
199         if (! vehicle_data[idx].pending)    {
200             continue;
201         }
202         if (! dbus_pending_call_get_completed(vehicle_data[idx].pending))   {
203             continue;
204         }
205
206         dbus_message = dbus_pending_call_steal_reply(vehicle_data[idx].pending);
207         if (! dbus_message) {
208             apfw_trace("get_vehicle_info: (%s) NO reply", vehicle_info[idx].property);
209             continue;
210         }
211
212         if (dbus_message_get_type(dbus_message) == DBUS_MESSAGE_TYPE_ERROR) {
213             dbus_message_unref(dbus_message);
214             dbus_pending_call_unref(vehicle_data[idx].pending);
215             vehicle_data[idx].pending = NULL;
216             vehicle_data[idx].errcount ++;
217             if (vehicle_data[idx].errcount <= 5)    {
218                 apfw_trace("get_vehicle_info: (%s) reply error", vehicle_info[idx].property);
219             }
220             continue;
221         }
222
223         dbus_message_iter_init(dbus_message, &iter_head);
224         dbus_message_iter_recurse(&iter_head, &iter);
225
226         type = dbus_message_iter_get_arg_type(&iter);
227         switch (type)   {
228         case DBUS_TYPE_INT32:
229             dbus_message_iter_get_basic(&iter, &i32);
230             vehicle_data[idx].val = (double)i32;
231             break;
232         case DBUS_TYPE_INT16:
233             dbus_message_iter_get_basic(&iter, &i16);
234             vehicle_data[idx].val = (double)i16;
235             break;
236         case DBUS_TYPE_UINT32:
237             dbus_message_iter_get_basic(&iter, &u32);
238             vehicle_data[idx].val = (double)u32;
239             break;
240         case DBUS_TYPE_UINT16:
241             dbus_message_iter_get_basic(&iter, &u16);
242             vehicle_data[idx].val = (double)u16;
243             break;
244         case DBUS_TYPE_BOOLEAN:
245             dbus_message_iter_get_basic(&iter, &b);
246             if (b)      vehicle_data[idx].val = (double)1.0;
247             else        vehicle_data[idx].val = (double)0.0;
248             break;
249         case DBUS_TYPE_BYTE:
250             dbus_message_iter_get_basic(&iter, &u8);
251             vehicle_data[idx].val = (double)u8;
252             break;
253         case DBUS_TYPE_DOUBLE:
254             dbus_message_iter_get_basic(&iter, &d64);
255             vehicle_data[idx].val = (double)d64;
256             break;
257         default:
258             apfw_warn("get_vehicle_info: (%s) illegal data type(0x%02x)",
259                       vehicle_info[idx].property, ((int)type) & 0x0ff);
260             break;
261         }
262 #if 0   /* too many logout, change to comment   */
263         apfw_trace("get_vehicle_info: %s = %d",
264                    vehicle_info[idx].property, (int)vehicle_data[idx].val);
265 #endif  /* too many logout, change to comment   */
266
267         /* free message and pending     */
268         dbus_message_unref(dbus_message);
269         dbus_pending_call_unref(vehicle_data[idx].pending);
270         vehicle_data[idx].pending = NULL;
271     };
272     return ICO_SYC_EOK;
273 }
274
275 /*--------------------------------------------------------------------------*/
276 /**
277  * @brief   rule_engine_wake: judge a run regulation state(static function)
278  *
279  * @param[in]   user_data       user data(unused)
280  * @return      always ECORE_CALLBACK_RENEW(periodic timer)
281  */
282 /*--------------------------------------------------------------------------*/
283 static Eina_Bool
284 rule_engine_wake(void *user_data)
285 {
286     int     idx;
287     int     i;
288     ico_apc_reguration_control_t    wkcontrol[ICO_UXF_CATEGORY_MAX];
289     ico_apc_reguration_control_t    change;
290     double  VehicleSpeed = 0.0;
291     int     ShiftPosition = ICO_SYC_APC_REGULATION_SHIFT_NEUTRALS;
292     int     Blinker = ICO_SYC_APC_REGULATION_BLINKER_NONE;
293
294     /* call UX-FW timer     */
295     ico_uxf_timer_wake(100);
296
297     memset(wkcontrol, 0, sizeof(ico_apc_reguration_control_t) * ncategory);
298
299     /* get reply (vehicle ifno) */
300     get_vehicle_info();
301
302     /* get vehicle info values  */
303     for (idx = 0; vehicle_data[idx].key; idx++)   {
304         if (vehicle_data[idx].key == ICO_SYC_VEHICLEINFO_VEHICLE_SPEED)   {
305             VehicleSpeed = (double)vehicle_data[idx].val;
306         }
307         else if (vehicle_data[idx].key == ICO_SYC_VEHICLEINFO_SHIFT_POSITION) {
308             ShiftPosition = (int)vehicle_data[idx].val;
309         }
310 #if 0   /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
311         else if (vehicle_data[idx].key == ICO_SYC_VEHICLEINFO_TURN_SIGNAL) {
312             Blinker = (int)vehicle_data[idx].val;
313         }
314 #else   /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
315         else if (vehicle_data[idx].key == ICO_SYC_VEHICLEINFO_LIGHT_LEFT) {
316             if (vehicle_data[idx].val == 0.0)   {
317                 if (Blinker == ICO_SYC_APC_REGULATION_BLINKER_LEFT) {
318                     Blinker = ICO_SYC_APC_REGULATION_BLINKER_NONE;
319                 }
320             }
321             else    {
322                 Blinker = ICO_SYC_APC_REGULATION_BLINKER_LEFT;
323             }
324         }
325         else if (vehicle_data[idx].key == ICO_SYC_VEHICLEINFO_LIGHT_RIGHT) {
326             if (vehicle_data[idx].val == 0.0)   {
327                 if (Blinker == ICO_SYC_APC_REGULATION_BLINKER_RIGHT)    {
328                     Blinker = ICO_SYC_APC_REGULATION_BLINKER_NONE;
329                 }
330             }
331             else    {
332                 Blinker = ICO_SYC_APC_REGULATION_BLINKER_RIGHT;
333             }
334         }
335 #endif  /* use LightStatus, because AMB not support access of TurnSignal by D-Bus   */
336     }
337
338     /* Make control code            */
339     memcpy(wkcontrol, control, sizeof(ico_apc_reguration_control_t) * ncategory);
340
341     /* Check Vehicle Speed          */
342     for (idx = 0; idx < ncategory; idx++)   {
343         switch (category[idx].view) {
344         case ICO_UXF_POLICY_ALWAYS:
345             wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
346             break;
347         case ICO_UXF_POLICY_RUNNING:
348             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
349                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
350             else
351                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
352             break;
353         case ICO_UXF_POLICY_PARKED:
354             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
355                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
356             else
357                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
358             break;
359         case ICO_UXF_POLICY_SHIFT_PARKING:
360             if ((VehicleSpeed < ICO_SYC_APC_REGULATION_SPEED_RUNNING) &&
361                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_PARKING))
362                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
363             else
364                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
365             break;
366         case ICO_UXF_POLICY_SHIFT_REVERSES:
367             if (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES)
368                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
369             else
370                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
371             break;
372         case ICO_UXF_POLICY_BLINKER_LEFT:
373             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_LEFT) ||
374                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
375                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
376             else
377                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
378             break;
379         case ICO_UXF_POLICY_BLINKER_RIGHT:
380             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_RIGHT) ||
381                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
382                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_REGULATION;
383             else
384                 wkcontrol[idx].display = ICO_SYC_APC_REGULATION_NOREGULATION;
385             break;
386         default:
387             apfw_trace("rule_engine_wake: category(%d) has unknown view(%d)",
388                        idx, category[idx].view);
389             break;
390         }
391
392         switch (category[idx].sound)    {
393         case ICO_UXF_POLICY_ALWAYS:
394             wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
395             break;
396         case ICO_UXF_POLICY_RUNNING:
397             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
398                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
399             else
400                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
401             break;
402         case ICO_UXF_POLICY_PARKED:
403             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
404                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
405             else
406                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
407             break;
408         case ICO_UXF_POLICY_SHIFT_PARKING:
409             if (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_PARKING)
410                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
411             else
412                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
413             break;
414         case ICO_UXF_POLICY_SHIFT_REVERSES:
415             if (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES)
416                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
417             else
418                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
419             break;
420         case ICO_UXF_POLICY_BLINKER_LEFT:
421             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_LEFT) ||
422                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
423                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
424             else
425                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
426             break;
427         case ICO_UXF_POLICY_BLINKER_RIGHT:
428             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_RIGHT) ||
429                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
430                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_REGULATION;
431             else
432                 wkcontrol[idx].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
433             break;
434         default:
435             apfw_trace("rule_engine_wake: category(%d) has unknown sound(%d)",
436                        idx, category[idx].sound);
437             break;
438         }
439
440         switch (category[idx].input)    {
441         case ICO_UXF_POLICY_ALWAYS:
442             wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
443             break;
444         case ICO_UXF_POLICY_RUNNING:
445             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
446                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
447             else
448                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
449             break;
450         case ICO_UXF_POLICY_PARKED:
451             if (VehicleSpeed >= ICO_SYC_APC_REGULATION_SPEED_RUNNING)
452                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
453             else
454                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
455             break;
456         case ICO_UXF_POLICY_SHIFT_PARKING:
457             if (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_PARKING)
458                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
459             else
460                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
461             break;
462         case ICO_UXF_POLICY_SHIFT_REVERSES:
463             if (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES)
464                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
465             else
466                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
467             break;
468         case ICO_UXF_POLICY_BLINKER_LEFT:
469             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_LEFT) ||
470                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
471                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
472             else
473                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
474             break;
475         case ICO_UXF_POLICY_BLINKER_RIGHT:
476             if ((Blinker != ICO_SYC_APC_REGULATION_BLINKER_RIGHT) ||
477                 (ShiftPosition == ICO_SYC_APC_REGULATION_SHIFT_REVERSES))
478                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_REGULATION;
479             else
480                 wkcontrol[idx].input = ICO_SYC_APC_REGULATION_NOREGULATION;
481             break;
482         default:
483             apfw_trace("rule_engine_wake: category(%d) has unknown input(%d)",
484                        idx, category[idx].input);
485             break;
486         }
487     }
488
489     for (idx = 0; idx < ncategory; idx++) {
490         if ((control[idx].display != wkcontrol[idx].display) ||
491             (control[idx].sound != wkcontrol[idx].sound) ||
492             (control[idx].input != wkcontrol[idx].input))   {
493             apfw_trace("rule_engine_wake: Category.%d view.%d>%d sound.%d>%d inp.%d>%d",
494                        idx, control[idx].display, wkcontrol[idx].display,
495                        control[idx].sound, wkcontrol[idx].sound,
496                        control[idx].input, wkcontrol[idx].input);
497
498             if (nregulation_cb > 0)  {
499                 if (control[idx].display != wkcontrol[idx].display)
500                     change.display = wkcontrol[idx].display;
501                 else
502                     change.display = ICO_SYC_APC_REGULATION_NOCHANGE;
503                 if (control[idx].sound != wkcontrol[idx].sound)
504                     change.sound = wkcontrol[idx].sound;
505                 else
506                     change.sound = ICO_SYC_APC_REGULATION_NOCHANGE;
507                 if (control[idx].input != wkcontrol[idx].input)
508                     change.input = wkcontrol[idx].input;
509                 else
510                     change.input = ICO_SYC_APC_REGULATION_NOCHANGE;
511
512                 for (i = 0; i < nregulation_cb; i++)    {
513                     (*regulation_cb[i])(idx, change, regulation_cb_user_data[i]);
514                 }
515             }
516             control[idx].display = wkcontrol[idx].display;
517             control[idx].sound = wkcontrol[idx].sound;
518             control[idx].input = wkcontrol[idx].input;
519         }
520     }
521     /* send request to AMB                  */
522     request_vehicle_info();
523
524     return ECORE_CALLBACK_RENEW;
525 }
526
527 /*--------------------------------------------------------------------------*/
528 /**
529  * @brief   ico_syc_apc_regulation_init: initialize regulation control
530  *
531  * @param       none
532  * @return      result
533  * @retval      ICO_SYC_EOK     success
534  * @retval      ICO_SYC_EIO     error(D-Bus initialize error)
535  */
536 /*--------------------------------------------------------------------------*/
537 int
538 ico_syc_apc_regulation_init(void)
539 {
540     int     i;
541     DBusError dbus_error;
542
543     apfw_trace("ico_syc_apc_regulation_init: Enter");
544
545     /* get configurations                           */
546     confsys = (Ico_Uxf_Sys_Config *)ico_uxf_getSysConfig();
547
548     if (! confsys) {
549         apfw_trace("ico_syc_apc_regulation_init: Leave(can not read configuration)");
550         return ICO_SYC_EIO;
551     }
552     ncategory = confsys->categoryNum;
553     category = confsys->category;
554
555     memset(vehicle_data, 0, sizeof(vehicle_data));
556     memset(control, 0, sizeof(control));
557     for (i = 0; i <ncategory; i++)  {
558         control[i].display = ICO_SYC_APC_REGULATION_NOREGULATION;
559         control[i].sound = ICO_SYC_APC_REGULATION_NOREGULATION;
560         control[i].input = ICO_SYC_APC_REGULATION_NOREGULATION;
561     }
562
563     /* Reset D-Bus error        */
564     dbus_error_init(&dbus_error);
565
566     /* Get D-Bus connection     */
567     dbus_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error);
568     if (! dbus_connection){
569         apfw_warn("ico_syc_apc_regulation_init: Leave(ERROR dbus_bus_get)" );
570         return ICO_SYC_EIO;
571     }
572
573     /* send request to AMB                  */
574     request_vehicle_info();
575
576     vehicle_timer = ecore_timer_add(0.1, rule_engine_wake, NULL);
577     if (! vehicle_timer)    {
578         apfw_error("ico_syc_apc_regulation_init: Leave(Can not create Ecore timer)");
579     }
580
581     apfw_trace("ico_syc_apc_regulation_init: Leave(EOK)");
582
583     return ICO_SYC_EOK;
584 }
585
586 /*--------------------------------------------------------------------------*/
587 /**
588  * @brief   ico_syc_apc_regulation_term: terminate regulation control
589  *
590  * @param       none
591  * @return      always ICO_SYC_EOK(success)
592  */
593 /*--------------------------------------------------------------------------*/
594 int
595 ico_syc_apc_regulation_term(void)
596 {
597     apfw_trace("ico_syc_apc_regulation_term: Enter");
598
599     if (! confsys) {
600         apfw_trace("ico_syc_apc_regulation_term: Leave(not initialized)");
601         return ICO_SYC_EOK;
602     }
603     ecore_timer_del(vehicle_timer);
604
605     confsys = NULL;
606
607     apfw_trace("ico_syc_apc_regulation_term: Leave(EOK)");
608     return ICO_SYC_EOK;
609 }
610
611 /*--------------------------------------------------------------------------*/
612 /**
613  * @brief   ico_syc_apc_regulation_listener: set regulation control listener
614  *
615  * @param[in]   func            listener function
616  * @param[in]   user_data       user data
617  * @return      none
618  */
619 /*--------------------------------------------------------------------------*/
620 void
621 ico_syc_apc_regulation_listener(ico_apc_regulation_cb_t func, void *user_data)
622 {
623     int     idx;
624
625     if (func == NULL)   {
626         nregulation_cb = 0;
627         return;
628     }
629
630     for (idx = 0; idx < nregulation_cb; idx++)  {
631         if (regulation_cb[idx] == func) break;
632     }
633     if (idx >= nregulation_cb)  {
634         if (nregulation_cb >= ICO_SYC_APC_REGULATION_LISTENERS) {
635             apfw_error("ico_syc_apc_regulation_listener: Too many listeners");
636             return;
637         }
638         idx = nregulation_cb;
639         nregulation_cb ++;
640     }
641     regulation_cb[idx] = func;
642     regulation_cb_user_data[idx] = user_data;
643
644     for (idx = 0; idx < ncategory; idx++) {
645         (*func)(idx, control[idx], user_data);
646     }
647 }
648
649 /*--------------------------------------------------------------------------*/
650 /**
651  * @brief   ico_syc_apc_regulation_app_visible: get display regulation status
652  *
653  * @param[in]   category    category Id
654  * @return      result
655  * @retval      TRUE        The application of this category can use the display
656  * @retval      FALSE       The application of this category can not use the display
657  */
658 /*--------------------------------------------------------------------------*/
659 int
660 ico_syc_apc_regulation_app_visible(const int category)
661 {
662     if ((category < 0) || (category >= ICO_UXF_CATEGORY_MAX))    {
663         apfw_warn("ico_syc_apc_regulation_app_visible: Illegal category(%d)", category);
664         return TRUE;
665     }
666     if (control[category].display == ICO_SYC_APC_REGULATION_NOREGULATION)   {
667         return TRUE;
668     }
669     return FALSE;
670 }
671
672 /*--------------------------------------------------------------------------*/
673 /**
674  * @brief   ico_syc_apc_regulation_app_sound: get sound reguration status
675  *
676  * @param[in]   category    category Id
677  * @return      result
678  * @retval      TRUE        The application of this category can use the sound output
679  * @retval      FALSE       The application of this category can not use the sound output
680  */
681 /*--------------------------------------------------------------------------*/
682 int
683 ico_syc_apc_regulation_app_sound(const int category)
684 {
685     if ((category < 0) || (category >= ICO_UXF_CATEGORY_MAX))    {
686         apfw_warn("ico_syc_apc_regulation_app_sound: Illegal category(%d)", category);
687         return TRUE;
688     }
689     if (control[category].sound == ICO_SYC_APC_REGULATION_NOREGULATION) {
690         return TRUE;
691     }
692     return FALSE;
693 }
694
695 /*--------------------------------------------------------------------------*/
696 /**
697  * @brief   ico_syc_apc_regulation_app_input: get input switch reguration status
698  *
699  * @param[in]   category    category Id
700  * @return      result
701  * @retval      TRUE        The application of this category is available with an input
702  * @retval      FALSE       The application of this category is not available with an input
703  */
704 /*--------------------------------------------------------------------------*/
705 int
706 ico_syc_apc_regulation_app_input(const int category)
707 {
708     if ((category < 0) || (category >= ICO_UXF_CATEGORY_MAX))    {
709         apfw_warn("ico_syc_apc_regulation_app_input: Illegal category(%d)", category);
710         return TRUE;
711     }
712     if (control[category].input == ICO_SYC_APC_REGULATION_NOREGULATION) {
713         return TRUE;
714     }
715     return FALSE;
716 }
717