resource-manager: Add API for fine-tuned event listening
[platform/core/system/libsyscommon.git] / src / resource-manager / resource-manager.c
1 /* MIT License
2  *
3  * Copyright (c) 2023 Samsung Electronics Co., Ltd.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to deal
7  * in the Software without restriction, including without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9  * copies of the Software, and to permit persons to whom the Software is furnished
10  * to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in all
13  * copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21  * THE SOFTWARE. */
22
23 #include <assert.h>
24 #include <glib.h>
25 #include <stdio.h>
26 #include <json.h>
27 #include <sys/time.h>
28 #include <pthread.h>
29
30 #include "libsyscommon/resource-manager.h"
31 #include "libsyscommon/resource-type.h"
32
33 #define BIT64_INDEX(id)                         (63 - __builtin_clzll(id))
34 #define RESOURCE_ATTR_INDEX(id)                 BIT64_INDEX(id)
35 #define RESOURCE_CTRL_INDEX(id)                 BIT64_INDEX(id)
36 #define RESOURCE_FLAG_VISIBILITY_MASK           (SYSCOMMON_RESMAN_RESOURCE_FLAG_PRIVATE \
37                                                 | SYSCOMMON_RESMAN_RESOURCE_FLAG_PUBLIC)
38 #define RESOURCE_ATTR_FLAG_VISIBILITY_MASK      (SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PRIVATE \
39                                                 | SYSCOMMON_RESMAN_RESOURCE_ATTR_FLAG_PUBLIC)
40
41 #define INSTANCE_TYPE_NORMAL                    0
42 #define INSTANCE_TYPE_MONITOR                   1
43
44 #define RESOURCE_TYPE_ALL                       (-1)
45 #define RESOURCE_ATTR_ALL                       (~0ULL)
46
47 struct syscommon_resman_resource {
48         char *name;
49         int id;
50         const struct syscommon_resman_resource_driver *driver;
51         int resource_type; /* which type of resource */
52         int instance_type; /* how resource instance operates */
53
54         int num_attrs;
55         const struct syscommon_resman_resource_attribute *attrs;
56         struct syscommon_resman_resource_attribute_value *attrs_value;
57         int num_ctrls;
58         const struct syscommon_resman_resource_control *ctrls;
59
60         u_int64_t flag;
61
62         void *priv;
63
64         u_int64_t attr_interest;
65         u_int64_t attr_supported;
66 };
67
68 struct attribute_is_supported_ops {
69         bool (*is_supported)(int resource_id,
70                    const struct syscommon_resman_resource_attribute *attr);
71         int (*get)(int resource_id,
72                    const struct syscommon_resman_resource_attribute *attr,
73                    void *data);
74 };
75
76 struct resource_event_data {
77         int id;
78         int resource_type;
79         int attr_mask;
80         syscommon_resman_resource_event_cb callback;
81         void *user_data;
82 };
83
84 static int set_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask);
85 static int unset_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask);
86 static bool is_resource_attr_interested(struct syscommon_resman_resource *resource, u_int64_t interest_mask);
87 static void
88 notify_resource_event(int resource_type, int resource_id, u_int64_t attr_id, const void *data, int count);
89
90 static GList *g_resource_driver_head;
91 static GList *g_resource_event_data_list;
92
93 /**
94  * key: resource_id, value: struct syscommon_resman_resource
95  */
96 static GHashTable *g_resource_hash_table;
97
98 /**
99  * key: resource_type, value: head of resource_id list
100  */
101 static GHashTable *g_resource_id_list_hash_table;
102
103 static GList** find_resource_id_list(int resource_type)
104 {
105         if (!g_resource_id_list_hash_table)
106                 return NULL;
107
108         return g_hash_table_lookup(g_resource_id_list_hash_table, GINT_TO_POINTER(resource_type));
109 }
110
111 static int clear_sign_bit(unsigned int val)
112 {
113         return (int)((val << 1) >> 1);
114 }
115
116 static int init_resource_id(void)
117 {
118         int val;
119         struct timeval tv;
120
121         gettimeofday(&tv, NULL);
122         val = tv.tv_sec * 1000 + tv.tv_usec / 1000;
123         return clear_sign_bit(val);
124 }
125
126 static int alloc_resource_id(void)
127 {
128         static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
129         static int resource_id = -1;
130         int ret;
131
132         pthread_mutex_lock(&lock);
133
134         if (resource_id < 0)
135                 resource_id = init_resource_id();
136
137         ret = resource_id;
138         resource_id = clear_sign_bit(resource_id + 1);
139
140         pthread_mutex_unlock(&lock);
141
142         return ret;
143 }
144
145 static void free_resource(struct syscommon_resman_resource *resource)
146 {
147         free(resource->name);
148         resource->name = NULL;
149
150         unset_resource_attr_interest(resource, resource->attr_interest);
151         free(resource->attrs_value);
152         resource->attrs_value = NULL;
153
154         resource->attrs = NULL;
155         resource->num_attrs = 0;
156
157         free(resource);
158 }
159
160 static void delete_resource(void *data)
161 {
162         GList **resource_id_list = NULL;
163         struct syscommon_resman_resource *resource = (struct syscommon_resman_resource *) data;
164
165         if (!resource)
166                 return;
167
168         if (resource->driver && resource->driver->ops.delete)
169                 resource->driver->ops.delete(resource->id);
170
171         resource_id_list = find_resource_id_list(resource->resource_type);
172         if (resource_id_list) {
173                 *resource_id_list = g_list_remove(*resource_id_list, GINT_TO_POINTER(resource->id));
174                 if (*resource_id_list == NULL)
175                         g_hash_table_remove(g_resource_id_list_hash_table, resource_id_list);
176         }
177
178         free_resource(resource);
179 }
180
181 static int add_resource(struct syscommon_resman_resource *resource)
182 {
183         GList **resource_id_list = NULL;
184
185         if (!resource)
186                 return -EINVAL;
187
188         if (!g_resource_hash_table) {
189                 g_resource_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, delete_resource);
190                 if (!g_resource_hash_table)
191                         return -ENOMEM;
192         }
193
194         if (!g_resource_id_list_hash_table) {
195                 g_resource_id_list_hash_table = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, free);
196                 if (!g_resource_id_list_hash_table)
197                         return -ENOMEM;
198         }
199
200         resource_id_list = find_resource_id_list(resource->resource_type);
201         if (!resource_id_list) {
202                 resource_id_list = (GList **) calloc(1, sizeof(void *));
203                 if (!resource_id_list)
204                         return -ENOMEM;
205                 g_hash_table_insert(g_resource_id_list_hash_table, GINT_TO_POINTER(resource->resource_type), resource_id_list);
206         }
207
208         g_hash_table_insert(g_resource_hash_table, GINT_TO_POINTER(resource->id), resource);
209         *resource_id_list = g_list_append(*resource_id_list, GINT_TO_POINTER(resource->id));
210
211         return 0;
212 }
213
214 static struct syscommon_resman_resource * find_resource(int id)
215 {
216         if (!g_resource_hash_table)
217                 return NULL;
218
219         return g_hash_table_lookup(g_resource_hash_table, GINT_TO_POINTER(id));
220 }
221
222 static gint __compare_resource_type(gconstpointer data, gconstpointer input)
223 {
224         struct syscommon_resman_resource_driver *driver;
225         int type = *(int *)input;
226
227         driver = (struct syscommon_resman_resource_driver *)data;
228
229         if (driver && driver->type == type)
230                 return 0;
231         return -1;
232 }
233
234 const struct syscommon_resman_resource_driver *
235 syscommon_resman_find_resource_driver(int resource_type)
236 {
237         GList *node;
238
239         node = g_list_find_custom(g_resource_driver_head,
240                         &resource_type, __compare_resource_type);
241
242         if (!node)
243                 return NULL;
244         return (struct syscommon_resman_resource_driver *)node->data;
245 }
246
247 int syscommon_resman_get_number_of_resource_instance(int resource_type, int *n_instance)
248 {
249         GList **resource_id_list = NULL;
250
251         resource_id_list = find_resource_id_list(resource_type);
252         if (!resource_id_list)
253                 *n_instance = 0;
254         else
255                 *n_instance = g_list_length(*resource_id_list);
256
257         return 0;
258 }
259
260 int syscommon_resman_get_resource_id(int resource_type, int *resource_id)
261 {
262         GList **resource_id_list = NULL;
263
264         resource_id_list = find_resource_id_list(resource_type);
265         if (!resource_id_list)
266                 return -EINVAL;
267
268         *resource_id = GPOINTER_TO_INT(g_list_nth_data(*resource_id_list, 0));
269
270         return 0;
271 }
272
273 void
274 syscommon_resman_add_resource_driver(const struct syscommon_resman_resource_driver *driver)
275 {
276         if (!driver)
277                 return;
278
279         g_resource_driver_head =
280                         g_list_append(g_resource_driver_head, (gpointer)driver);
281 }
282
283 void
284 syscommon_resman_remove_resource_driver(const struct syscommon_resman_resource_driver *driver)
285 {
286         if (!driver)
287                 return;
288
289         g_resource_driver_head =
290                         g_list_remove(g_resource_driver_head, (gpointer)driver);
291 }
292
293 void syscommon_resman_delete_resource(int resource_id)
294 {
295         if (!g_resource_hash_table)
296                 return;
297
298         g_hash_table_remove(g_resource_hash_table, GINT_TO_POINTER(resource_id));
299 }
300
301 static int
302 create_resource(int *resource_id, int resource_type, int instance_type)
303 {
304         const struct syscommon_resman_resource_driver *driver = NULL;
305         struct syscommon_resman_resource *resource = NULL;
306         int i, ret;
307
308         if (!resource_id)
309                 return -EINVAL;
310
311         driver = syscommon_resman_find_resource_driver(resource_type);
312         if (!driver)
313                 return -EINVAL;
314
315         resource = calloc(1, sizeof(*resource));
316         if (!resource)
317                 return -ENOMEM;
318
319         resource->id = alloc_resource_id();
320         resource->resource_type = resource_type;
321         resource->instance_type = instance_type;
322         resource->name = g_strdup(driver->name);
323         resource->driver = driver;
324         resource->num_attrs = driver->num_attrs;
325         resource->attrs = driver->attrs;
326         resource->attrs_value = calloc(resource->num_attrs,
327                                         sizeof(*resource->attrs_value));
328         if (!resource->attrs_value) {
329                 free_resource(resource);
330                 return -ENOMEM;
331         }
332
333         ret = add_resource(resource);
334         if (ret < 0) {
335                 free_resource(resource);
336                 return ret;
337         }
338
339         for (i = 0; i < resource->num_attrs; i++)
340                 resource->attrs_value[i].type = driver->attrs[i].type;
341
342         resource->ctrls = driver->ctrls;
343         resource->num_ctrls = driver->num_ctrls;
344         resource->flag = SYSCOMMON_RESMAN_RESOURCE_FLAG_PRIVATE;
345
346         if (driver->ops.create) {
347                 ret = driver->ops.create(resource->id);
348                 if (ret < 0) {
349                         g_hash_table_remove(g_resource_hash_table, GINT_TO_POINTER(resource->id));
350                         return ret;
351                 }
352         }
353
354         *resource_id = resource->id;
355
356         return 0;
357 }
358
359 static int set_resource_attr_interest_all(struct syscommon_resman_resource *resource)
360 {
361         u_int64_t all;
362
363         if (!resource || !resource->num_attrs)
364                 return -EINVAL;
365
366         all = (1ULL << resource->num_attrs) - 1;
367
368         return set_resource_attr_interest(resource, all);
369 }
370
371 int
372 syscommon_resman_create_resource(int *resource_id, int resource_type)
373 {
374         int ret;
375         struct syscommon_resman_resource *resource = NULL;
376
377         ret = create_resource(resource_id, resource_type, INSTANCE_TYPE_NORMAL);
378         if (ret < 0)
379                 return ret;
380
381         resource = find_resource(*resource_id);
382         assert(resource);
383
384         ret = set_resource_attr_interest_all(resource);
385         if (ret < 0) {
386                 syscommon_resman_delete_resource(resource->id);
387                 return ret;
388         }
389
390         return 0;
391 }
392
393 int
394 syscommon_resman_monitor_create_resource(int *resource_id, int resource_type)
395 {
396         return create_resource(resource_id, resource_type, INSTANCE_TYPE_MONITOR);
397 }
398
399 int
400 syscommon_resman_set_resource_flag(int resource_id, u_int64_t flag_mask)
401 {
402         struct syscommon_resman_resource *resource = find_resource(resource_id);
403
404         if (!resource)
405                 return -EINVAL;
406
407         resource->flag = flag_mask;
408         return 0;
409 }
410
411 int
412 syscommon_resman_set_resource_control(int resource_id, u_int64_t ctrl_id, const void *data)
413 {
414         const struct syscommon_resman_resource_control *ctrl;
415         int ctrl_index;
416         int ret;
417         struct syscommon_resman_resource *resource;
418
419         if (ctrl_id == 0)
420                 return -EINVAL;
421
422         resource = find_resource(resource_id);
423         if (!resource)
424                 return -EINVAL;
425
426         ctrl_index = RESOURCE_CTRL_INDEX(ctrl_id);
427         if (ctrl_index >= resource->num_ctrls)
428                 return -EINVAL;
429
430         ctrl = &resource->ctrls[ctrl_index];
431         if (!ctrl->ops.set)
432                 return -ENOTSUP;
433
434         ret = ctrl->ops.set(resource_id, ctrl, data);
435         if (ret < 0)
436                 return ret;
437
438         return 0;
439 }
440
441 const char *
442 syscommon_resman_get_resource_control_name(int resource_id, u_int64_t ctrl_id)
443 {
444         const struct syscommon_resman_resource_control *ctrl;
445         int ctrl_index;
446         struct syscommon_resman_resource *resource;
447
448         if (ctrl_id == 0)
449                 return NULL;
450
451         resource = find_resource(resource_id);
452         if (!resource)
453                 return NULL;
454
455         ctrl_index = RESOURCE_CTRL_INDEX(ctrl_id);
456         if (ctrl_index >= resource->num_ctrls)
457                 return NULL;
458
459         ctrl = &resource->ctrls[ctrl_index];
460
461         return ctrl->name;
462 }
463
464 static int
465 update_resource_attr(struct syscommon_resman_resource *resource, u_int64_t attr_id)
466 {
467         int attr_index;
468         const struct syscommon_resman_resource_attribute *attr = NULL;
469         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
470         int ret;
471
472         if (!resource || attr_id == 0)
473                 return -EINVAL;
474
475         attr_index = RESOURCE_ATTR_INDEX(attr_id);
476         if (attr_index >= resource->num_attrs)
477                 return -EINVAL;
478
479         attr = &resource->attrs[attr_index];
480
481         if (!attr->ops.get)
482                 return -EINVAL;
483
484         attr_value = &resource->attrs_value[attr_index];
485
486         ret = attr->ops.get(resource->id, attr, attr_value->data);
487         if (ret < 0)
488                 return ret;
489
490         return 0;
491 }
492
493 static int
494 update_resource_attr_with_1_user_data(struct syscommon_resman_resource *resource, u_int64_t attr_id,
495                                         u_int64_t *user_data1, int user_count1)
496 {
497         int attr_index;
498         const struct syscommon_resman_resource_attribute *attr = NULL;
499         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
500         int ret;
501
502         if (!resource || attr_id == 0)
503                 return -EINVAL;
504
505         attr_index = RESOURCE_ATTR_INDEX(attr_id);
506         if (attr_index >= resource->num_attrs)
507                 return -EINVAL;
508
509         attr = &resource->attrs[attr_index];
510
511         if (!attr->ops.get)
512                 return -EINVAL;
513
514         attr_value = &resource->attrs_value[attr_index];
515
516         ret = attr->ops.get_with_1_user_data(resource->id, attr,
517                                 user_data1, user_count1, attr_value->data);
518         if (ret < 0)
519                 return ret;
520
521         return 0;
522 }
523
524 static int
525 update_resource_attr_with_2_user_data(struct syscommon_resman_resource *resource, u_int64_t attr_id,
526                                         u_int64_t *user_data1, u_int64_t *user_data2,
527                                         int user_count1, int user_count2)
528 {
529         int attr_index;
530         const struct syscommon_resman_resource_attribute *attr = NULL;
531         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
532         int ret;
533
534         if (!resource || attr_id == 0)
535                 return -EINVAL;
536
537         attr_index = RESOURCE_ATTR_INDEX(attr_id);
538         if (attr_index >= resource->num_attrs)
539                 return -EINVAL;
540
541         attr = &resource->attrs[attr_index];
542
543         if (!attr->ops.get)
544                 return -EINVAL;
545
546         attr_value = &resource->attrs_value[attr_index];
547
548         ret = attr->ops.get_with_2_user_data(resource->id, attr,
549                                 user_data1, user_data2,
550                                 user_count1, user_count2, attr_value->data);
551         if (ret < 0)
552                 return ret;
553
554         return 0;
555 }
556
557 static int
558 monitor_update_resource_attr(struct syscommon_resman_resource *resource, u_int64_t attr_id)
559 {
560         int attr_index;
561         const struct syscommon_resman_resource_attribute *attr = NULL;
562         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
563         int ret;
564
565         if (!resource || attr_id == 0)
566                 return -EINVAL;
567
568         attr_index = RESOURCE_ATTR_INDEX(attr_id);
569         if (attr_index >= resource->num_attrs)
570                 return -EINVAL;
571
572         attr = &resource->attrs[attr_index];
573
574         if (!attr->monitor_ops.get)
575                 return -EINVAL;
576
577         attr_value = &resource->attrs_value[attr_index];
578
579         ret = attr->monitor_ops.get(resource->id, attr, attr_value->data);
580         if (ret < 0)
581                 return ret;
582
583         return 0;
584 }
585
586 static bool is_valid_resource(struct syscommon_resman_resource *resource, int instance_type)
587 {
588         return (resource && resource->instance_type == instance_type);
589 }
590
591 int
592 syscommon_resman_monitor_update_resource_attrs(int resource_id)
593 {
594         int i, ret;
595         struct syscommon_resman_resource *resource = find_resource(resource_id);
596
597         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
598                 return -EINVAL;
599
600         if (resource->driver && resource->driver->ops.prepare_update) {
601                 ret = resource->driver->ops.prepare_update(resource->id);
602                 if (ret < 0)
603                         return ret;
604         }
605
606         for (i = 0; i < resource->num_attrs; i++) {
607                 if (!(resource->attrs[i].id & resource->attr_interest))
608                         continue;
609                 monitor_update_resource_attr(resource, resource->attrs[i].id);
610         }
611
612         return 0;
613 }
614
615 static const struct syscommon_resman_resource_attribute *
616 get_resource_attr(struct syscommon_resman_resource *resource, u_int64_t attr_id)
617 {
618         int attr_index;
619
620         if (!resource || attr_id == 0)
621                 return NULL;
622
623         attr_index = RESOURCE_ATTR_INDEX(attr_id);
624         if (attr_index >= resource->num_attrs)
625                 return NULL;
626
627         return &resource->attrs[attr_index];
628 }
629
630 const struct syscommon_resman_resource_attribute *
631 syscommon_resman_get_resource_attr(int resource_id, u_int64_t attr_id)
632 {
633         struct syscommon_resman_resource *resource = find_resource(resource_id);
634
635         return get_resource_attr(resource, attr_id);
636 }
637
638 static struct syscommon_resman_resource_attribute_value *
639 get_resource_attr_value(struct syscommon_resman_resource *resource, u_int64_t attr_id)
640 {
641         int attr_index;
642
643         if (!resource || attr_id == 0)
644                 return NULL;
645
646         attr_index = RESOURCE_ATTR_INDEX(attr_id);
647         if (attr_index >= resource->num_attrs)
648                 return NULL;
649
650         return &resource->attrs_value[attr_index];
651 }
652
653 struct syscommon_resman_resource_attribute_value *
654 syscommon_resman_get_resource_attr_value(int resource_id, u_int64_t attr_id)
655 {
656         struct syscommon_resman_resource *resource = find_resource(resource_id);
657
658         return get_resource_attr_value(resource, attr_id);
659 }
660
661 static int select_attribute_is_supported_ops(int instance_type,
662         const struct syscommon_resman_resource_attribute *attr, struct attribute_is_supported_ops *ops)
663 {
664         assert(attr);
665         assert(ops);
666
667         switch (instance_type) {
668         case INSTANCE_TYPE_NORMAL:
669                 ops->is_supported = attr->ops.is_supported;
670                 ops->get = attr->ops.get;
671                 return 0;
672         case INSTANCE_TYPE_MONITOR:
673                 ops->is_supported = attr->monitor_ops.is_supported;
674                 ops->get = attr->monitor_ops.get;
675                 return 0;
676         default:
677                 assert(0); // unreachable
678         }
679
680         return -EINVAL;
681 }
682
683 static int is_resource_attr_supported(struct syscommon_resman_resource *resource, u_int64_t attr_id, bool *supported)
684 {
685         const struct syscommon_resman_resource_attribute *attr = NULL;
686         int attr_index;
687         int ret;
688         bool is_supported = false;
689         struct attribute_is_supported_ops ops = { 0 , };
690
691         if (!supported)
692                 return -EINVAL;
693
694         if (!resource || attr_id == 0) {
695                 *supported = false;
696                 return -EINVAL;
697         }
698
699         attr_index = RESOURCE_ATTR_INDEX(attr_id);
700         if (attr_index >= resource->num_attrs) {
701                 *supported = false;
702                 return -EINVAL;
703         }
704
705         attr = &resource->attrs[attr_index];
706
707         /* Select ops for testing support by instance type */
708         ret = select_attribute_is_supported_ops(resource->instance_type, attr, &ops);
709         if (ret < 0) {
710                 *supported = false;
711                 return ret;
712         }
713
714         if (attr->id & resource->attr_supported) {
715                 is_supported = true;
716         } else if (ops.is_supported) {
717                 is_supported = ops.is_supported(resource->id, attr);
718         } else if (ops.get) {
719                 /*
720                  * Optionally, if .is_supported ops is not implemented,
721                  * use .get ops in order to check whether the resource attribute
722                  * is supported or not.
723                  */
724                 char data[SYSCOMMON_RESMAN_BUFF_MAX] = {0, };
725
726                 ret = ops.get(resource->id, attr, (void *)data);
727                 is_supported = (ret < 0) ? false :  true;
728         }
729
730         if (is_supported)
731                 resource->attr_supported |= attr->id;
732
733         *supported = is_supported;
734
735         return 0;
736 }
737
738 int
739 syscommon_resman_is_resource_attr_supported(int resource_id, u_int64_t attr_id, bool *supported)
740 {
741         struct syscommon_resman_resource *resource = find_resource(resource_id);
742
743         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
744                 return -EINVAL;
745
746         return is_resource_attr_supported(resource, attr_id, supported);
747 }
748
749 int
750 syscommon_resman_monitor_is_resource_attr_supported(int resource_id, u_int64_t attr_id, bool *supported)
751 {
752         struct syscommon_resman_resource *resource = find_resource(resource_id);
753
754         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
755                 return -EINVAL;
756
757         return is_resource_attr_supported(resource, attr_id, supported);
758 }
759
760 static bool
761 check_attr_validate(struct syscommon_resman_resource *resource,
762                     u_int64_t attr_id, int type)
763 {
764         const struct syscommon_resman_resource_attribute *attr;
765
766         attr = get_resource_attr(resource, attr_id);
767         if (!attr)
768                 return false;
769
770         if (attr->type != type)
771                 return false;
772
773         if (!(attr->id & resource->attr_interest))
774                 return false;
775
776         return true;
777 }
778
779 static json_object *
780 _get_resource_attr_json(const struct syscommon_resman_resource_attribute *attr,
781                         const struct syscommon_resman_resource_attribute_value *attr_value)
782 {
783         json_object *jobj_attr, *jobj_attr_name, *jobj_attr_type, *jobj_attr_value, *jobj_temp;
784         struct syscommon_resman_array_value *array;
785         int i;
786
787         switch (attr->type) {
788         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
789                 jobj_attr_value = json_object_new_int(*((int32_t *)attr_value->data));
790                 break;
791         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
792                 jobj_attr_value = json_object_new_int(*((u_int32_t *)attr_value->data));
793                 break;
794         case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
795                 jobj_attr_value = json_object_new_int64(*((int64_t *)attr_value->data));
796                 break;
797         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
798                 jobj_attr_value = json_object_new_uint64(*((u_int64_t *)attr_value->data));
799                 break;
800         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
801                 jobj_attr_value = json_object_new_double(*((double *)attr_value->data));
802                 break;
803         case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
804                 jobj_attr_value = json_object_new_string((char *)attr_value->data);
805                 break;
806         case SYSCOMMON_RESMAN_DATA_TYPE_ARRAY:
807                 array = attr_value->data;
808
809                 jobj_attr_value = json_object_new_array();
810
811                 switch (array->type) {
812                 case SYSCOMMON_RESMAN_DATA_TYPE_INT:
813                         for (i = 0; i < array->length; i++) {
814                                 int32_t *item = array->data;
815
816                                 jobj_temp = json_object_new_int(item[i]);
817                                 json_object_array_add(jobj_attr_value, jobj_temp);
818                         }
819                         break;
820                 case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
821                         for (i = 0; i < array->length; i++) {
822                                 u_int32_t *item = array->data;
823
824                                 jobj_temp = json_object_new_int(item[i]);
825                                 json_object_array_add(jobj_attr_value, jobj_temp);
826                         }
827                         break;
828                 case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
829                         for (i = 0; i < array->length; i++) {
830                                 int64_t *item = array->data;
831
832                                 jobj_temp = json_object_new_int64(item[i]);
833                                 json_object_array_add(jobj_attr_value, jobj_temp);
834                         }
835                         break;
836                 case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
837                         for (i = 0; i < array->length; i++) {
838                                 u_int64_t *item = array->data;
839
840                                 jobj_temp = json_object_new_uint64(item[i]);
841                                 json_object_array_add(jobj_attr_value, jobj_temp);
842                         }
843                         break;
844                 case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
845                         for (i = 0; i < array->length; i++) {
846                                 double *item = array->data;
847
848                                 jobj_temp = json_object_new_double(item[i]);
849                                 json_object_array_add(jobj_attr_value, jobj_temp);
850                         }
851                         break;
852                 case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
853                         for (i = 0; i < array->length; i++) {
854                                 char **item = array->data;
855
856                                 jobj_temp = json_object_new_string(item[i]);
857                                 json_object_array_add(jobj_attr_value, jobj_temp);
858                         }
859                         break;
860                 default:
861                         json_object_put(jobj_attr_value);
862                         jobj_attr_value = json_object_new_null();
863                 }
864                 break;
865         default:
866                 jobj_attr_value = json_object_new_null();
867         }
868         jobj_attr = json_object_new_object();
869
870         jobj_attr_name = json_object_new_string(attr->name);
871         /*
872          * Since actually JSON format has no data type limitation itself, in many
873          * cases except converting JSON into json-c, type is not required. So,
874          * for the case of converting JSON generated here to json-c object again
875          * json_type is stored in each attributes.
876          */
877         jobj_attr_type = json_object_new_int(json_object_get_type(jobj_attr_value));
878
879         json_object_object_add(jobj_attr, "name", jobj_attr_name);
880         json_object_object_add(jobj_attr, "json_type", jobj_attr_type);
881         json_object_object_add(jobj_attr, "value", jobj_attr_value);
882
883         return jobj_attr;
884 }
885
886 static void _put_resource_attr_json(json_object *jobj_attr)
887 {
888         json_object *jobj_attr_value;
889
890         json_object_object_del(jobj_attr, "name");
891         json_object_object_del(jobj_attr, "json_type");
892
893         if (json_object_object_get_ex(jobj_attr, "value", &jobj_attr_value) &&
894                         json_object_is_type(jobj_attr_value, json_type_array))
895                 json_object_array_del_idx(jobj_attr_value, 0,
896                                           json_object_array_length(jobj_attr_value));
897
898         json_object_object_del(jobj_attr, "value");
899 }
900
901 int
902 syscommon_resman_monitor_get_resource_attrs_json(int resource_id, char **json_string)
903 {
904         json_object *jobj_root, *jobj_res_name, *jobj_res_type, *jobj_res_attrs, *jobj_attr;
905         const struct syscommon_resman_resource_attribute *attr;
906         const struct syscommon_resman_resource_attribute_value *attr_value;
907         struct syscommon_resman_resource *resource = find_resource(resource_id);
908         int i;
909
910         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
911                 return -EINVAL;
912
913         jobj_root = json_object_new_object();
914
915         jobj_res_name = json_object_new_string(resource->name);
916         jobj_res_type = json_object_new_int(resource->resource_type);
917         jobj_res_attrs = json_object_new_array();
918
919         for (i = 0; i < resource->num_attrs; i++) {
920                 if (!(resource->attrs[i].id & resource->attr_interest))
921                         continue;
922
923                 attr = &resource->attrs[i];
924                 attr_value = &resource->attrs_value[i];
925
926                 jobj_attr = _get_resource_attr_json(attr, attr_value);
927
928                 json_object_array_add(jobj_res_attrs, jobj_attr);
929         }
930
931         json_object_object_add(jobj_root, "res_name", jobj_res_name);
932         json_object_object_add(jobj_root, "res_type", jobj_res_type);
933         json_object_object_add(jobj_root, "res_attrs", jobj_res_attrs);
934
935         *json_string = strdup(json_object_to_json_string(jobj_root));
936
937         for (i = 0; i < json_object_array_length(jobj_res_attrs); i++) {
938                 jobj_attr = json_object_array_get_idx(jobj_res_attrs, i);
939                 _put_resource_attr_json(jobj_attr);
940         }
941         json_object_array_del_idx(jobj_res_attrs, 0, json_object_array_length(jobj_res_attrs));
942
943         json_object_object_del(jobj_root, "res_attrs");
944         json_object_object_del(jobj_root, "res_type");
945         json_object_object_del(jobj_root, "res_name");
946         json_object_put(jobj_root);
947
948         return 0;
949 }
950
951 int
952 syscommon_resman_monitor_get_resource_attr_json(int resource_id, u_int64_t attr_id, char **json_string)
953 {
954         const struct syscommon_resman_resource_attribute *attr;
955         const struct syscommon_resman_resource_attribute_value *attr_value;
956         json_object *jobj_attr;
957         struct syscommon_resman_resource *resource = find_resource(resource_id);
958
959         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
960                 return -EINVAL;
961
962         attr = get_resource_attr(resource, attr_id);
963         attr_value = get_resource_attr_value(resource, attr_id);
964
965         if (!attr || !attr_value)
966                 return -EINVAL;
967
968         jobj_attr = _get_resource_attr_json(attr, attr_value);
969
970         *json_string = strdup(json_object_to_json_string(jobj_attr));
971
972         _put_resource_attr_json(jobj_attr);
973
974         return 0;
975 }
976
977 static json_object *
978 get_resource_driver_json(const struct syscommon_resman_resource_driver *driver)
979 {
980         json_object *jobj_drv, *jobj_drv_name, *jobj_drv_type;
981         json_object *jobj_drv_attrs_array, *jobj_drv_attr, *jobj_drv_ctrls_array, *jobj_drv_ctrl;
982         json_object *jobj_drv_attr_name, *jobj_drv_attr_type, *jobj_drv_attr_id;
983         json_object *jobj_drv_ctrl_name, *jobj_drv_ctrl_id;
984         const struct syscommon_resman_resource_attribute *attr;
985         const struct syscommon_resman_resource_control *ctrl;
986         int i;
987
988         jobj_drv = json_object_new_object();
989
990         jobj_drv_name = json_object_new_string(driver->name);
991         jobj_drv_type = json_object_new_int(driver->type);
992
993         jobj_drv_attrs_array = json_object_new_array();
994
995         for (i = 0; i < driver->num_attrs; i++) {
996                 attr = &driver->attrs[i];
997
998                 jobj_drv_attr = json_object_new_object();
999
1000                 jobj_drv_attr_name = json_object_new_string(attr->name);
1001                 jobj_drv_attr_type = json_object_new_int(attr->type);
1002                 jobj_drv_attr_id = json_object_new_uint64(attr->id);
1003
1004                 json_object_object_add(jobj_drv_attr, "name", jobj_drv_attr_name);
1005                 json_object_object_add(jobj_drv_attr, "type", jobj_drv_attr_type);
1006                 json_object_object_add(jobj_drv_attr, "id", jobj_drv_attr_id);
1007
1008                 json_object_array_add(jobj_drv_attrs_array, jobj_drv_attr);
1009         }
1010
1011         jobj_drv_ctrls_array = json_object_new_array();
1012
1013         for (i = 0; i < driver->num_ctrls; i++) {
1014                 ctrl = &driver->ctrls[i];
1015
1016                 jobj_drv_ctrl = json_object_new_object();
1017
1018                 jobj_drv_ctrl_name = json_object_new_string(ctrl->name);
1019                 jobj_drv_ctrl_id = json_object_new_uint64(ctrl->id);
1020
1021                 json_object_object_add(jobj_drv_ctrl, "name", jobj_drv_ctrl_name);
1022                 json_object_object_add(jobj_drv_ctrl, "id", jobj_drv_ctrl_id);
1023
1024                 json_object_array_add(jobj_drv_ctrls_array, jobj_drv_ctrl);
1025         }
1026
1027         json_object_object_add(jobj_drv, "name", jobj_drv_name);
1028         json_object_object_add(jobj_drv, "type", jobj_drv_type);
1029         json_object_object_add(jobj_drv, "attrs", jobj_drv_attrs_array);
1030         json_object_object_add(jobj_drv, "ctrls", jobj_drv_ctrls_array);
1031
1032         return jobj_drv;
1033 }
1034
1035 static void put_resource_driver_json(json_object *jobj_drv)
1036 {
1037         json_object *jobj_array, *jobj_obj;
1038         int i;
1039
1040         if (json_object_object_get_ex(jobj_drv, "ctrls", &jobj_array)) {
1041                 for (i = 0; i < json_object_array_length(jobj_array); i++) {
1042                         jobj_obj = json_object_array_get_idx(jobj_array, i);
1043
1044                         json_object_object_del(jobj_obj, "id");
1045                         json_object_object_del(jobj_obj, "name");
1046                 }
1047                 json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array));
1048         }
1049
1050         if (json_object_object_get_ex(jobj_drv, "attrs", &jobj_array)) {
1051                 for (i = 0; i < json_object_array_length(jobj_array); i++) {
1052                         jobj_obj = json_object_array_get_idx(jobj_array, i);
1053
1054                         json_object_object_del(jobj_obj, "id");
1055                         json_object_object_del(jobj_obj, "type");
1056                         json_object_object_del(jobj_obj, "name");
1057                 }
1058                 json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array));
1059         }
1060
1061         json_object_object_del(jobj_drv, "ctrls");
1062         json_object_object_del(jobj_drv, "attrs");
1063         json_object_object_del(jobj_drv, "type");
1064         json_object_object_del(jobj_drv, "name");
1065 }
1066
1067 int syscommon_resman_get_resource_list_json(char **json_string)
1068 {
1069         const struct syscommon_resman_resource_driver *driver;
1070         json_object *jobj_root, *jobj_drvs_array, *jobj_drv;
1071         int i;
1072
1073         jobj_root = json_object_new_object();
1074         jobj_drvs_array = json_object_new_array();
1075
1076         for (i = 0; i < g_list_length(g_resource_driver_head); i++) {
1077                 driver = g_list_nth(g_list_first(g_resource_driver_head), i)->data;
1078
1079                 jobj_drv = get_resource_driver_json(driver);
1080                 json_object_array_add(jobj_drvs_array, jobj_drv);
1081         }
1082
1083         json_object_object_add(jobj_root, "resources", jobj_drvs_array);
1084
1085         *json_string = strdup(json_object_to_json_string(jobj_root));
1086
1087         for (i = 0; i < json_object_array_length(jobj_drvs_array); i++) {
1088                 jobj_drv = json_object_array_get_idx(jobj_drvs_array, i);
1089
1090                 put_resource_driver_json(jobj_drv);
1091         }
1092         json_object_array_del_idx(jobj_drvs_array, 0, json_object_array_length(jobj_drvs_array));
1093
1094         json_object_object_del(jobj_root, "resources");
1095         json_object_put(jobj_root);
1096
1097         return 0;
1098 }
1099
1100 static int
1101 get_resource_attr_value_data(struct syscommon_resman_resource *resource, u_int64_t attr_id, enum syscommon_resman_data_type type, void *data)
1102 {
1103         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
1104
1105         if (!check_attr_validate(resource, attr_id, type))
1106                 return -EINVAL;
1107
1108         attr_value = get_resource_attr_value(resource, attr_id);
1109         if (!attr_value)
1110                 return -EINVAL;
1111
1112         switch (type) {
1113         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
1114                 *(int *) data = *((int32_t *) attr_value->data);
1115                 break;
1116         case  SYSCOMMON_RESMAN_DATA_TYPE_INT64:
1117                 *(int64_t *) data = *((int64_t *) attr_value->data);
1118                 break;
1119         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
1120                 *(u_int32_t *) data = *((u_int32_t *)attr_value->data);
1121                 break;
1122         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
1123         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_1_USER_DATA:
1124         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_2_USER_DATA:
1125                 *(u_int64_t *) data = *((u_int64_t *)attr_value->data);
1126                 break;
1127         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
1128                 *(double *) data = *((double *)attr_value->data);
1129                 break;
1130         case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
1131                 strncpy(data, (char *)attr_value->data, SYSCOMMON_RESMAN_BUFF_MAX);
1132                 break;
1133         case SYSCOMMON_RESMAN_DATA_TYPE_ARRAY:
1134                 *(struct syscommon_resman_array_value **) data = (struct syscommon_resman_array_value *)attr_value->data;
1135                 break;
1136         case SYSCOMMON_RESMAN_DATA_TYPE_PTR:
1137                 *(void **) data = attr_value->data;
1138                 break;
1139         case SYSCOMMON_RESMAN_DATA_TYPE_BOOLEAN:
1140         case SYSCOMMON_RESMAN_DATA_TYPE_NUM:
1141         default:
1142                 return -EINVAL;
1143         }
1144
1145         return 0;
1146 }
1147
1148 int
1149 syscommon_resman_get_resource_attr_int(int resource_id, u_int64_t attr_id, int32_t *data)
1150 {
1151         struct syscommon_resman_resource *resource = find_resource(resource_id);
1152         int ret;
1153
1154         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1155                 return -EINVAL;
1156
1157         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT))
1158                 return -EINVAL;
1159
1160         ret = update_resource_attr(resource, attr_id);
1161         if (ret < 0)
1162                 return ret;
1163
1164         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT, data);
1165 }
1166
1167 int
1168 syscommon_resman_get_resource_attr_int64(int resource_id, u_int64_t attr_id, int64_t *data)
1169 {
1170         struct syscommon_resman_resource *resource = find_resource(resource_id);
1171         int ret;
1172
1173         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1174                 return -EINVAL;
1175
1176         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT64))
1177                 return -EINVAL;
1178
1179         ret = update_resource_attr(resource, attr_id);
1180         if (ret < 0)
1181                 return ret;
1182
1183         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT64, data);
1184 }
1185
1186 int
1187 syscommon_resman_get_resource_attr_uint(int resource_id, u_int64_t attr_id, u_int32_t *data)
1188 {
1189         struct syscommon_resman_resource *resource = find_resource(resource_id);
1190         int ret;
1191
1192         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1193                 return -EINVAL;
1194
1195         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT))
1196                 return -EINVAL;
1197
1198         ret = update_resource_attr(resource, attr_id);
1199         if (ret < 0)
1200                 return ret;
1201
1202         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT, data);
1203 }
1204
1205 int
1206 syscommon_resman_get_resource_attr_uint64(int resource_id, u_int64_t attr_id, u_int64_t *data)
1207 {
1208         struct syscommon_resman_resource *resource = find_resource(resource_id);
1209         int ret;
1210
1211         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1212                 return -EINVAL;
1213
1214         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64))
1215                 return -EINVAL;
1216
1217         ret = update_resource_attr(resource, attr_id);
1218         if (ret < 0)
1219                 return ret;
1220
1221         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64, data);
1222 }
1223
1224 int
1225 syscommon_resman_get_resource_attr_uint64_with_1_user_data(int resource_id, u_int64_t attr_id, u_int64_t *user_data1, u_int64_t *data)
1226 {
1227         struct syscommon_resman_resource *resource = find_resource(resource_id);
1228         int ret;
1229
1230         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1231                 return -EINVAL;
1232
1233         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_1_USER_DATA))
1234                 return -EINVAL;
1235
1236         ret = update_resource_attr_with_1_user_data(resource, attr_id, user_data1, 1);
1237         if (ret < 0)
1238                 return ret;
1239
1240         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_1_USER_DATA, data);
1241 }
1242
1243 int
1244 syscommon_resman_get_resource_attr_uint64_with_2_user_data(int resource_id, u_int64_t attr_id, u_int64_t *user_data1, u_int64_t *user_data2, u_int64_t *data)
1245 {
1246         struct syscommon_resman_resource *resource = find_resource(resource_id);
1247         int ret;
1248
1249         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1250                 return -EINVAL;
1251
1252         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_2_USER_DATA))
1253                 return -EINVAL;
1254
1255         ret = update_resource_attr_with_2_user_data(resource, attr_id, user_data1, user_data2, 1, 1);
1256         if (ret < 0)
1257                 return ret;
1258
1259         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_2_USER_DATA, data);
1260 }
1261
1262 int
1263 syscommon_resman_get_resource_attr_double(int resource_id, u_int64_t attr_id, double *data)
1264 {
1265         struct syscommon_resman_resource *resource = find_resource(resource_id);
1266         int ret;
1267
1268         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1269                 return -EINVAL;
1270
1271         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE))
1272                 return -EINVAL;
1273
1274         ret = update_resource_attr(resource, attr_id);
1275         if (ret < 0)
1276                 return ret;
1277
1278         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE, data);
1279 }
1280
1281 int
1282 syscommon_resman_get_resource_attr_string(int resource_id, u_int64_t attr_id, char *data)
1283 {
1284         struct syscommon_resman_resource *resource = find_resource(resource_id);
1285         int ret;
1286
1287         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1288                 return -EINVAL;
1289
1290         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_STRING))
1291                 return -EINVAL;
1292
1293         ret = update_resource_attr(resource, attr_id);
1294         if (ret < 0)
1295                 return ret;
1296
1297         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_STRING, data);
1298 }
1299
1300 int
1301 syscommon_resman_get_resource_attr_array(int resource_id, u_int64_t attr_id, struct syscommon_resman_array_value **data)
1302 {
1303         struct syscommon_resman_resource *resource = find_resource(resource_id);
1304         int ret;
1305
1306         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1307                 return -EINVAL;
1308
1309         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_ARRAY))
1310                 return -EINVAL;
1311
1312         ret = update_resource_attr(resource, attr_id);
1313         if (ret < 0)
1314                 return ret;
1315
1316         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_ARRAY, data);
1317 }
1318
1319 int
1320 syscommon_resman_get_resource_attr_ptr(int resource_id, u_int64_t attr_id, void **data)
1321 {
1322         struct syscommon_resman_resource *resource = find_resource(resource_id);
1323         int ret;
1324
1325         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1326                 return -EINVAL;
1327
1328         if (!check_attr_validate(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_PTR))
1329                 return -EINVAL;
1330
1331         ret = update_resource_attr(resource, attr_id);
1332         if (ret < 0)
1333                 return ret;
1334
1335         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_PTR, data);
1336 }
1337
1338 int
1339 syscommon_resman_monitor_get_resource_attr_int(int resource_id, u_int64_t attr_id, int32_t *data)
1340 {
1341         struct syscommon_resman_resource *resource = find_resource(resource_id);
1342
1343         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1344                 return -EINVAL;
1345
1346         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT, data);
1347 }
1348
1349 int
1350 syscommon_resman_monitor_get_resource_attr_int64(int resource_id, u_int64_t attr_id, int64_t *data)
1351 {
1352         struct syscommon_resman_resource *resource = find_resource(resource_id);
1353
1354         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1355                 return -EINVAL;
1356
1357         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT64, data);
1358 }
1359
1360 int
1361 syscommon_resman_monitor_get_resource_attr_uint(int resource_id, u_int64_t attr_id, u_int32_t *data)
1362 {
1363         struct syscommon_resman_resource *resource = find_resource(resource_id);
1364
1365         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1366                 return -EINVAL;
1367
1368         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT, data);
1369 }
1370
1371 int
1372 syscommon_resman_monitor_get_resource_attr_uint64(int resource_id, u_int64_t attr_id, u_int64_t *data)
1373 {
1374         struct syscommon_resman_resource *resource = find_resource(resource_id);
1375
1376         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1377                 return -EINVAL;
1378
1379         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64, data);
1380 }
1381
1382 int
1383 syscommon_resman_monitor_get_resource_attr_double(int resource_id, u_int64_t attr_id, double *data)
1384 {
1385         struct syscommon_resman_resource *resource = find_resource(resource_id);
1386
1387         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1388                 return -EINVAL;
1389
1390         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE, data);
1391 }
1392
1393 int
1394 syscommon_resman_monitor_get_resource_attr_string(int resource_id, u_int64_t attr_id, char *data)
1395 {
1396         struct syscommon_resman_resource *resource = find_resource(resource_id);
1397
1398         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1399                 return -EINVAL;
1400
1401         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_STRING, data);
1402 }
1403
1404 int
1405 syscommon_resman_monitor_get_resource_attr_array(int resource_id, u_int64_t attr_id, struct syscommon_resman_array_value **data)
1406 {
1407         struct syscommon_resman_resource *resource = find_resource(resource_id);
1408
1409         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1410                 return -EINVAL;
1411
1412         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_ARRAY, data);
1413 }
1414
1415 int
1416 syscommon_resman_monitor_get_resource_attr_ptr(int resource_id, u_int64_t attr_id, void **data)
1417 {
1418         struct syscommon_resman_resource *resource = find_resource(resource_id);
1419
1420         if (!is_valid_resource(resource, INSTANCE_TYPE_MONITOR))
1421                 return -EINVAL;
1422
1423         return get_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_PTR, data);
1424 }
1425
1426 static int
1427 set_resource_attr_value_data(struct syscommon_resman_resource *resource,
1428         u_int64_t attr_id, enum syscommon_resman_data_type type, const void *data, int count)
1429 {
1430         const struct syscommon_resman_resource_attribute *attr = NULL;
1431         struct syscommon_resman_resource_attribute_value *attr_value = NULL;
1432         int ret;
1433
1434         if (!data)
1435                 return -EINVAL;
1436
1437         if (!check_attr_validate(resource, attr_id, type))
1438                 return -EINVAL;
1439
1440         attr = get_resource_attr(resource, attr_id);
1441         if (!attr || !attr->ops.set)
1442                 return -EINVAL;
1443
1444         attr_value = get_resource_attr_value(resource, attr_id);
1445         if (!attr_value)
1446                 return -EINVAL;
1447
1448         ret = attr->ops.set(resource->id, attr, data, count);
1449         if (ret < 0)
1450                 return ret;
1451
1452         /* TODO: We need to discuss about updating attr_value->data after ops.set() */
1453         switch (type) {
1454         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
1455                 *((int32_t *) attr_value->data) = *(int32_t *) data;
1456                 break;
1457         case  SYSCOMMON_RESMAN_DATA_TYPE_INT64:
1458                 *((int64_t *) attr_value->data) = *(int64_t *) data;
1459                 break;
1460         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
1461                 *((u_int32_t *) attr_value->data) = *(u_int32_t *) data;
1462                 break;
1463         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
1464                 *((u_int64_t *) attr_value->data) = *(u_int64_t *) data;
1465                 break;
1466         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
1467                 *((double *) attr_value->data) = *(double *) data;
1468                 break;
1469         case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
1470                 strncpy((char *) attr_value->data, data, SYSCOMMON_RESMAN_BUFF_MAX);
1471                 break;
1472         case SYSCOMMON_RESMAN_DATA_TYPE_ARRAY:
1473                 attr_value->data = *(struct syscommon_resman_array_value **) data;
1474                 break;
1475         case SYSCOMMON_RESMAN_DATA_TYPE_PTR:
1476                 attr_value->data = *(void **) data;
1477                 break;
1478         case SYSCOMMON_RESMAN_DATA_TYPE_BOOLEAN:
1479         case SYSCOMMON_RESMAN_DATA_TYPE_NUM:
1480         default:
1481                 return -EINVAL;
1482         }
1483
1484         notify_resource_event(resource->resource_type, resource->id, attr_id, attr_value->data, count);
1485
1486         return 0;
1487 }
1488
1489 static int
1490 set_resource_attr_value_data_2_tuple(struct syscommon_resman_resource *resource,
1491         u_int64_t attr_id, enum syscommon_resman_data_type type,
1492         const void *data1, const void *data2,
1493         int count1, int count2)
1494 {
1495         const struct syscommon_resman_resource_attribute *attr = NULL;
1496         int ret;
1497
1498         if (!data1 || !data2)
1499                 return -EINVAL;
1500
1501         if (!check_attr_validate(resource, attr_id, type))
1502                 return -EINVAL;
1503
1504         attr = get_resource_attr(resource, attr_id);
1505         if (!attr)
1506                 return -EINVAL;
1507
1508         if (!attr->ops.set_2_tuple)
1509                 return -ENOTSUP;
1510
1511         ret = attr->ops.set_2_tuple(resource->id, attr,
1512                                         data1, data2, count1, count2);
1513         if (ret < 0)
1514                 return ret;
1515
1516         /**
1517          * FIXME: N-tuple data doesn't support the getter temporarily.
1518          * So that don't store the passed data to attr_value.
1519          * I will be implemented for getter on later.
1520          */
1521
1522         return 0;
1523 }
1524
1525 static int
1526 set_resource_attr_value_data_3_tuple(struct syscommon_resman_resource *resource,
1527         u_int64_t attr_id, enum syscommon_resman_data_type type,
1528         const void *data1, const void *data2, const void *data3,
1529         int count1, int count2, int count3)
1530 {
1531         const struct syscommon_resman_resource_attribute *attr = NULL;
1532         int ret;
1533
1534         if (!data1 || !data2 || !data3)
1535                 return -EINVAL;
1536
1537         if (!check_attr_validate(resource, attr_id, type))
1538                 return -EINVAL;
1539
1540         attr = get_resource_attr(resource, attr_id);
1541         if (!attr)
1542                 return -EINVAL;
1543
1544         if (!attr->ops.set_3_tuple)
1545                 return -ENOTSUP;
1546
1547         ret = attr->ops.set_3_tuple(resource->id, attr,
1548                                         data1, data2, data3,
1549                                         count1, count2, count3);
1550         if (ret < 0)
1551                 return ret;
1552
1553         /**
1554          * FIXME: N-tuple data doesn't support the getter temporarily.
1555          * So that don't store the passed data to attr_value.
1556          * I will be implemented for getter on later.
1557          */
1558
1559         return 0;
1560 }
1561
1562 static int
1563 set_resource_attr_value_data_4_tuple(struct syscommon_resman_resource *resource,
1564         u_int64_t attr_id, enum syscommon_resman_data_type type,
1565         const void *data1, const void *data2, const void *data3, const void *data4,
1566         int count1, int count2, int count3, int count4)
1567 {
1568         const struct syscommon_resman_resource_attribute *attr = NULL;
1569         int ret;
1570
1571         if (!data1 || !data2 || !data3 || !data4)
1572                 return -EINVAL;
1573
1574         if (!check_attr_validate(resource, attr_id, type))
1575                 return -EINVAL;
1576
1577         attr = get_resource_attr(resource, attr_id);
1578         if (!attr)
1579                 return -EINVAL;
1580
1581         if (!attr->ops.set_4_tuple)
1582                 return -ENOTSUP;
1583
1584         ret = attr->ops.set_4_tuple(resource->id, attr,
1585                                         data1, data2, data3, data4,
1586                                         count1, count2, count3, count4);
1587         if (ret < 0)
1588                 return ret;
1589
1590         /**
1591          * FIXME: N-tuple data doesn't support the getter temporarily.
1592          * So that don't store the passed data to attr_value.
1593          * I will be implemented for getter on later.
1594          */
1595
1596         return 0;
1597 }
1598
1599 int
1600 syscommon_resman_set_resource_attr_int(int resource_id, u_int64_t attr_id, int32_t data)
1601 {
1602         struct syscommon_resman_resource *resource = find_resource(resource_id);
1603
1604         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1605                 return -EINVAL;
1606
1607         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT, &data, 1);
1608 }
1609
1610 int
1611 syscommon_resman_set_resource_attr_int64(int resource_id, u_int64_t attr_id, int64_t data)
1612 {
1613         struct syscommon_resman_resource *resource = find_resource(resource_id);
1614
1615         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1616                 return -EINVAL;
1617
1618         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_INT64, &data, 1);
1619 }
1620
1621 int
1622 syscommon_resman_set_resource_attr_uint(int resource_id, u_int64_t attr_id, u_int32_t data)
1623 {
1624         struct syscommon_resman_resource *resource = find_resource(resource_id);
1625
1626         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1627                 return -EINVAL;
1628
1629         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT, &data, 1);
1630 }
1631
1632 int
1633 syscommon_resman_set_resource_attr_uint64(int resource_id, u_int64_t attr_id, u_int64_t data)
1634 {
1635         struct syscommon_resman_resource *resource = find_resource(resource_id);
1636
1637         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1638                 return -EINVAL;
1639
1640         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_UINT64, &data, 1);
1641 }
1642
1643 int
1644 syscommon_resman_set_resource_attr_double(int resource_id, u_int64_t attr_id, double data)
1645 {
1646         struct syscommon_resman_resource *resource = find_resource(resource_id);
1647
1648         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1649                 return -EINVAL;
1650
1651         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE, &data, 1);
1652 }
1653
1654 int
1655 syscommon_resman_set_resource_attr_string(int resource_id, u_int64_t attr_id, char data)
1656 {
1657         struct syscommon_resman_resource *resource = find_resource(resource_id);
1658
1659         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1660                 return -EINVAL;
1661
1662         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_STRING, &data, 1);
1663 }
1664
1665 int
1666 syscommon_resman_set_resource_attr_array(int resource_id, u_int64_t attr_id, void *data, int count)
1667 {
1668         struct syscommon_resman_resource *resource = find_resource(resource_id);
1669
1670         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1671                 return -EINVAL;
1672
1673         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_ARRAY, &data, count);
1674 }
1675
1676 int
1677 syscommon_resman_set_resource_attr_ptr(int resource_id, u_int64_t attr_id, void *data)
1678 {
1679         struct syscommon_resman_resource *resource = find_resource(resource_id);
1680
1681         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1682                 return -EINVAL;
1683
1684         return set_resource_attr_value_data(resource, attr_id, SYSCOMMON_RESMAN_DATA_TYPE_PTR, &data, 1);
1685 }
1686
1687 int
1688 syscommon_resman_set_resource_attr_uint64_2(int resource_id, u_int64_t attr_id,
1689                                         u_int64_t data1, u_int64_t data2)
1690 {
1691         struct syscommon_resman_resource *resource = find_resource(resource_id);
1692
1693         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1694                 return -EINVAL;
1695
1696         return set_resource_attr_value_data_2_tuple(resource, attr_id,
1697                                         SYSCOMMON_RESMAN_DATA_TYPE_2_UINT64,
1698                                         &data1, &data2, 1, 1);
1699 }
1700
1701 int
1702 syscommon_resman_set_resource_attr_uint64_3(int resource_id, u_int64_t attr_id,
1703                                         u_int64_t data1, u_int64_t data2, u_int64_t data3)
1704 {
1705         struct syscommon_resman_resource *resource = find_resource(resource_id);
1706
1707         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1708                 return -EINVAL;
1709
1710         return set_resource_attr_value_data_3_tuple(resource, attr_id,
1711                                         SYSCOMMON_RESMAN_DATA_TYPE_3_UINT64,
1712                                         &data1, &data2, &data3, 1, 1, 1);
1713 }
1714
1715 int
1716 syscommon_resman_set_resource_attr_uint64_4(int resource_id, u_int64_t attr_id,
1717                                         u_int64_t data1, u_int64_t data2, u_int64_t data3, u_int64_t data4)
1718 {
1719         struct syscommon_resman_resource *resource = find_resource(resource_id);
1720
1721         if (!is_valid_resource(resource, INSTANCE_TYPE_NORMAL))
1722                 return -EINVAL;
1723
1724         return set_resource_attr_value_data_4_tuple(resource, attr_id,
1725                                         SYSCOMMON_RESMAN_DATA_TYPE_4_UINT64,
1726                                         &data1, &data2, &data3, &data4, 1, 1, 1, 1);
1727 }
1728
1729 static inline bool
1730 is_resource_attr_visible(struct syscommon_resman_resource *resource,
1731                          const struct syscommon_resman_resource_attribute *attr)
1732 {
1733         u_int64_t res_visibility, attr_visibility;
1734
1735         res_visibility = resource->flag & RESOURCE_FLAG_VISIBILITY_MASK;
1736         attr_visibility = attr->flag & RESOURCE_ATTR_FLAG_VISIBILITY_MASK;
1737
1738         /* bigger visibility means smaller privilege */
1739         if (res_visibility > attr_visibility)
1740                 return false;
1741
1742         return true;
1743 }
1744
1745 static int
1746 set_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask)
1747 {
1748         struct syscommon_resman_resource_attribute_value *attr_value;
1749         int i, ret;
1750         bool supported;
1751         bool setter_only = false;
1752
1753         if (!resource)
1754                 return -EINVAL;
1755
1756         for (i = 0; i < resource->num_attrs; i++) {
1757                 if (!(resource->attrs[i].id & interest_mask))
1758                         continue;
1759
1760                 ret = is_resource_attr_supported(resource, resource->attrs[i].id, &supported);
1761                 if (ret < 0) {
1762                         goto err;
1763                 } else if (!supported) {
1764                         ret = -ENOTSUP;
1765                         goto err;
1766                 }
1767
1768                 if (!is_resource_attr_visible(resource, &resource->attrs[i])) {
1769                         ret = -EACCES;
1770                         goto err;
1771                 }
1772
1773                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
1774                 if (!attr_value) {
1775                         ret = -EINVAL;
1776                         goto err;
1777                 }
1778
1779                 if (resource->attrs[i].listener_ops.init) {
1780                         ret = resource->attrs[i].listener_ops.init(resource->id, &resource->attrs[i]);
1781                         if (ret < 0)
1782                                 goto err;
1783                 }
1784
1785                 /*
1786                  * In resource monitor, each resource has a lot of attributes, but
1787                  * only updated attributes are selected by clients on demand. So,
1788                  * instead of allocating memory at the resource creation, allocate
1789                  * at the set interest.
1790                  */
1791                 if (!attr_value->data) {
1792                         switch (attr_value->type) {
1793                         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
1794                                 attr_value->data = calloc(1, sizeof(int32_t));
1795                                 break;
1796                         case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
1797                                 attr_value->data = calloc(1, sizeof(int64_t));
1798                                 break;
1799                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
1800                                 attr_value->data = calloc(1, sizeof(u_int32_t));
1801                                 break;
1802                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
1803                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_1_USER_DATA:
1804                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_2_USER_DATA:
1805                                 attr_value->data = calloc(1, sizeof(u_int64_t));
1806                                 break;
1807                         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
1808                                 attr_value->data = calloc(1, sizeof(double));
1809                                 break;
1810                         case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
1811                                 attr_value->data = calloc(SYSCOMMON_RESMAN_BUFF_MAX, sizeof(char));
1812                                 break;
1813                         case SYSCOMMON_RESMAN_DATA_TYPE_ARRAY:
1814                                 attr_value->data = calloc(1, sizeof(struct syscommon_resman_array_value));
1815                                 break;
1816                         case SYSCOMMON_RESMAN_DATA_TYPE_2_UINT64:
1817                         case SYSCOMMON_RESMAN_DATA_TYPE_3_UINT64:
1818                         case SYSCOMMON_RESMAN_DATA_TYPE_4_UINT64:
1819                                 /**
1820                                  * FIXME: N-tuple data doesn't support the getter temporarily.
1821                                  * Don't store the passed data to attr_value.
1822                                  * So that don't allocate the memory for attr_value->data.
1823                                  * I will be implemented on later.
1824                                  */
1825                                 setter_only = true;
1826                                 break;
1827                         default:
1828                                 ret = -EINVAL;
1829                                 goto err;
1830                         }
1831
1832                         if (!setter_only && !attr_value->data) {
1833                                 ret = -ENOMEM;
1834                                 goto err;
1835                         }
1836                 }
1837         }
1838
1839         resource->attr_interest |= interest_mask;
1840
1841         return 0;
1842
1843 err:
1844         for (; i >= 0;  i--) {
1845                 if (!(resource->attrs[i].id & interest_mask))
1846                         continue;
1847
1848                 if (resource->attrs[i].listener_ops.exit)
1849                         resource->attrs[i].listener_ops.exit(resource->id, &resource->attrs[i]);
1850
1851                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
1852                 if (!attr_value)
1853                         continue;
1854
1855                 if (attr_value->data) {
1856                         free(attr_value->data);
1857                         attr_value->data = NULL;
1858                 }
1859         }
1860
1861         return ret;
1862 }
1863
1864 int
1865 syscommon_resman_set_resource_attr_interest(int resource_id, u_int64_t interest_mask)
1866 {
1867         struct syscommon_resman_resource *resource = find_resource(resource_id);
1868
1869         return set_resource_attr_interest(resource, interest_mask);
1870 }
1871
1872 static int
1873 unset_resource_attr_interest(struct syscommon_resman_resource *resource, u_int64_t interest_mask)
1874 {
1875         struct syscommon_resman_resource_attribute_value *attr_value;
1876         int i;
1877
1878         if (!resource)
1879                 return -EINVAL;
1880
1881         if (!is_resource_attr_interested(resource, interest_mask))
1882                 return -EINVAL;
1883
1884         for (i = 0; i < resource->num_attrs; i++) {
1885                 if (!(resource->attrs[i].id & interest_mask))
1886                         continue;
1887
1888                 if (resource->attrs[i].listener_ops.exit)
1889                         resource->attrs[i].listener_ops.exit(resource->id, &resource->attrs[i]);
1890
1891                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
1892                 if (!attr_value)
1893                         return -EINVAL;
1894
1895                 if (attr_value->data) {
1896                         switch (attr_value->type) {
1897                         case SYSCOMMON_RESMAN_DATA_TYPE_ARRAY:
1898                         {
1899                                 struct syscommon_resman_array_value *array = attr_value->data;
1900
1901                                 if (array->data) {
1902                                         free(array->data);
1903                                         array->data = NULL;
1904                                 }
1905                                 /* fall through */
1906                         }
1907                         case SYSCOMMON_RESMAN_DATA_TYPE_INT:
1908                         case SYSCOMMON_RESMAN_DATA_TYPE_INT64:
1909                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT:
1910                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64:
1911                         case SYSCOMMON_RESMAN_DATA_TYPE_DOUBLE:
1912                         case SYSCOMMON_RESMAN_DATA_TYPE_STRING:
1913                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_1_USER_DATA:
1914                         case SYSCOMMON_RESMAN_DATA_TYPE_UINT64_WITH_2_USER_DATA:
1915                                 free(attr_value->data);
1916                                 attr_value->data = NULL;
1917                                 break;
1918                         default:
1919                                 return -EINVAL;
1920                         }
1921                 }
1922         }
1923
1924         resource->attr_interest &= ~interest_mask;
1925
1926         return 0;
1927 }
1928
1929 int
1930 syscommon_resman_unset_resource_attr_interest(int resource_id, u_int64_t interest_mask)
1931 {
1932         struct syscommon_resman_resource *resource = find_resource(resource_id);
1933
1934         return unset_resource_attr_interest(resource, interest_mask);
1935 }
1936
1937 static bool
1938 is_resource_attr_interested(struct syscommon_resman_resource *resource,
1939                                              u_int64_t interest_mask)
1940 {
1941         if (!resource)
1942                 return false;
1943
1944         if (resource->attr_interest != (resource->attr_interest | interest_mask))
1945                 return false;
1946
1947         return true;
1948 }
1949
1950 bool
1951 syscommon_resman_is_resource_attr_interested(int resource_id, u_int64_t interest_mask)
1952 {
1953         struct syscommon_resman_resource *resource = find_resource(resource_id);
1954
1955         return is_resource_attr_interested(resource, interest_mask);
1956 }
1957
1958 static void
1959 notify_resource_event(int resource_type, int resource_id, u_int64_t attr_id, const void *data, int count)
1960 {
1961         GList *elem;
1962         struct resource_event_data *event_data;
1963
1964         for (elem = g_resource_event_data_list; elem; elem = elem->next) {
1965                 event_data = (struct resource_event_data *) elem->data;
1966
1967                 assert(event_data);
1968
1969                 if ((event_data->resource_type != RESOURCE_TYPE_ALL) && (event_data->resource_type != resource_type))
1970                         continue;
1971
1972                 if ((event_data->attr_mask & attr_id) == 0)
1973                         continue;
1974
1975                 event_data->callback(resource_type, resource_id, attr_id, data, event_data->user_data, count);
1976         }
1977 }
1978
1979 static gboolean find_resource_event_data(gconstpointer data, gconstpointer id)
1980 {
1981         const struct resource_event_data *_event_data = (const struct resource_event_data *) data;
1982         const int _id = *(const int *) id;
1983
1984         return (_event_data->id - _id);
1985 }
1986
1987 int syscommon_resman_subscribe_resource_attribute_event(int resource_type,
1988         u_int64_t attr_mask, syscommon_resman_resource_event_cb callback, void *user_data, int *id)
1989 {
1990         struct resource_event_data *event_data = NULL;
1991
1992         if (!callback || !id)
1993                 return -EINVAL;
1994
1995         event_data = calloc(1, sizeof(*event_data));
1996         if (!event_data)
1997                 return -ENOMEM;
1998
1999         *event_data = (struct resource_event_data) {
2000                 .id = alloc_resource_id(),
2001                 .resource_type = resource_type,
2002                 .attr_mask = attr_mask,
2003                 .callback = callback,
2004                 .user_data = user_data,
2005         };
2006
2007         g_resource_event_data_list = g_list_append(g_resource_event_data_list, event_data);
2008
2009         *id = event_data->id;
2010
2011         return 0;
2012 }
2013
2014 int syscommon_resman_subscribe_resource_event(int resource_type,
2015         syscommon_resman_resource_event_cb callback, void *user_data, int *id)
2016 {
2017         return syscommon_resman_subscribe_resource_attribute_event(resource_type,
2018                 RESOURCE_ATTR_ALL, callback, user_data, id);
2019 }
2020
2021 int syscommon_resman_subscribe_event(syscommon_resman_resource_event_cb callback,
2022         void *user_data, int *id)
2023 {
2024         return syscommon_resman_subscribe_resource_event(RESOURCE_TYPE_ALL, callback, user_data, id);
2025 }
2026
2027 void syscommon_resman_unsubscribe_event(int id)
2028 {
2029         GList *list;
2030
2031         list = g_list_find_custom(g_resource_event_data_list, &id, find_resource_event_data);
2032         if (!list)
2033                 return;
2034
2035         g_resource_event_data_list = g_list_remove_link(g_resource_event_data_list, list);
2036
2037         free(list->data);
2038         list->data = NULL;
2039         g_list_free(list);
2040 }
2041
2042 const char *
2043 syscommon_resman_get_resource_attr_name(int resource_id, u_int64_t attr_id)
2044 {
2045         const struct syscommon_resman_resource_attribute *attr;
2046         struct syscommon_resman_resource *resource = find_resource(resource_id);
2047
2048         attr = get_resource_attr(resource, attr_id);
2049         if (!attr)
2050                 return NULL;
2051
2052         return attr->name;
2053 }
2054
2055 const char
2056 *syscommon_resman_get_resource_name(int resource_id)
2057 {
2058         struct syscommon_resman_resource *resource = find_resource(resource_id);
2059
2060         return resource ? resource->name : NULL;
2061 }
2062
2063 void *
2064 syscommon_resman_get_resource_privdata(int resource_id)
2065 {
2066         struct syscommon_resman_resource *resource = find_resource(resource_id);
2067
2068         return resource ? resource->priv : NULL;
2069 }
2070
2071 int
2072 syscommon_resman_get_resource_type(int resource_id)
2073 {
2074         struct syscommon_resman_resource *resource = find_resource(resource_id);
2075
2076         return resource ? resource->resource_type : -EINVAL;
2077 }
2078
2079 int
2080 syscommon_resman_set_resource_privdata(int resource_id, void *priv)
2081 {
2082         struct syscommon_resman_resource *resource = find_resource(resource_id);
2083
2084         if (!resource)
2085                 return -EINVAL;
2086
2087         resource->priv = priv;
2088
2089         return 0;
2090 }
2091
2092 static void init_resource_driver(gpointer data, gpointer udata)
2093 {
2094         struct syscommon_resman_resource_driver *driver = (struct syscommon_resman_resource_driver *) data;
2095         int ret = 0;
2096
2097         if (driver && driver->ops.init) {
2098                 ret = driver->ops.init();
2099                 if (ret < 0)
2100                         syscommon_resman_remove_resource_driver(driver);
2101         }
2102 }
2103
2104 static void exit_resource_driver(gpointer data, gpointer udata)
2105 {
2106         struct syscommon_resman_resource_driver *driver = (struct syscommon_resman_resource_driver *) data;
2107
2108         if (driver && driver->ops.exit)
2109                 driver->ops.exit();
2110 }
2111
2112 void syscommon_resman_init_resource_drivers(void)
2113 {
2114         g_list_foreach(g_resource_driver_head, init_resource_driver, NULL);
2115 }
2116
2117 void syscommon_resman_exit_resource_drivers(void)
2118 {
2119         g_list_foreach(g_resource_driver_head, exit_resource_driver, NULL);
2120 }