fa68256c19a8ac810c8f894518ee7c2acd7854c6
[platform/core/system/pass.git] / src / util / resource.c
1 /*
2  * PASS (Power Aware System Service)
3  *
4  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18
19 #include <glib.h>
20 #include <stdio.h>
21 #include <json.h>
22 #include <sys/time.h>
23
24 #include <util/common.h>
25 #include <util/resource.h>
26 #include <util/log.h>
27
28 #define RESOURCE_ATTR_MASK                      (ULLONG_MAX)
29 #define BIT64_INDEX(id)                         (63 - __builtin_clzll(id))
30 #define RESOURCE_ATTR_INDEX(id)                 BIT64_INDEX(id)
31 #define RESOURCE_CTRL_INDEX(id)                 BIT64_INDEX(id)
32
33 struct resource {
34         int id;
35         char *name;
36         const struct resource_driver *driver;
37         int type;
38         void *priv;
39
40         int num_attrs;
41         const struct resource_attribute *attrs;
42         struct resource_attribute_value *attrs_value;
43         int num_ctrls;
44         const struct resource_control *ctrls;
45         u_int64_t attr_interest;
46         u_int64_t attr_supported;
47
48         int64_t ts_start;
49         int64_t ts_end;
50 };
51
52 static int g_resource_id;
53 static GList *g_resource_driver_head;
54 static GList *g_resource_device_head;
55
56 static gint __compare_resource_type(gconstpointer data, gconstpointer input)
57 {
58         struct resource_driver *driver = (struct resource_driver *)data;
59         int type = *(int *)input;
60
61         if (driver->type == type)
62                 return 0;
63         return -1;
64 }
65
66 static const struct resource_driver *find_resource_driver(int resource_type)
67 {
68         GList *node;
69
70         node = g_list_find_custom(g_resource_driver_head,
71                         &resource_type, __compare_resource_type);
72
73         if (!node)
74                 return NULL;
75         return (struct resource_driver *)node->data;
76 }
77
78 void add_resource_driver(const struct resource_driver *driver)
79 {
80         if (!driver)
81                 return;
82
83         g_resource_driver_head =
84                         g_list_append(g_resource_driver_head, (gpointer)driver);
85 }
86
87 void remove_resource_driver(const struct resource_driver *driver)
88 {
89         if (!driver)
90                 return;
91
92         g_resource_driver_head =
93                         g_list_remove(g_resource_driver_head, (gpointer)driver);
94 }
95
96 int get_resource_device_count_all(void)
97 {
98         return g_list_length(g_resource_device_head);
99 }
100
101 int get_resource_device_count(int resource_type)
102 {
103         GList *node;
104         struct resource_device *device;
105         const struct resource_driver *driver;
106         int count = 0;
107
108         for (node = g_resource_device_head; node != NULL; node = node->next) {
109                 device = node->data;
110                 if (device->type == resource_type)
111                         count++;
112         }
113
114         if (count > 0)
115                 return count;
116
117         driver = find_resource_driver(resource_type);
118         if (!driver)
119                 return -EINVAL;
120
121         if (driver->flag & RESOURCE_FLAG_COUNT_ONLY_ONE)
122                 return 1;
123         else if (driver->flag & RESOURCE_FLAG_PROCESS)
124                 return -EINVAL;
125
126         return 0;
127 }
128
129 const struct resource_device *find_resource_device(int resource_type,
130                                                    int resource_index)
131 {
132         GList *node;
133         const struct resource_device *device;
134
135         for (node = g_resource_device_head; node != NULL; node = node->next) {
136                 device = node->data;
137                 if (device->type == resource_type &&
138                                 device->index == resource_index)
139                         return device;
140         }
141
142         return NULL;
143 }
144
145 int add_resource_device(struct resource_device *device)
146 {
147         int count;
148
149         if (!device)
150                 return -EINVAL;
151
152         count = get_resource_device_count(device->type);
153         device->index = count;
154
155         g_resource_device_head =
156                         g_list_append(g_resource_device_head, (gpointer)device);
157
158         return 0;
159 }
160
161 void remove_resource_device(struct resource_device *device)
162 {
163         if (!device)
164                 return;
165
166         g_resource_device_head =
167                         g_list_remove(g_resource_device_head, (gpointer)device);
168 }
169
170 static void do_delete_resource(struct resource *resource)
171 {
172         if (!resource->name)
173                 free(resource->name);
174         if (!resource->attrs_value)
175                 free(resource->attrs_value);
176         resource->attrs = NULL;
177         resource->num_attrs = 0;
178
179         free(resource);
180 }
181
182 void delete_resource(struct resource *resource)
183 {
184         if (!resource)
185                 return;
186
187         if (resource->driver && resource->driver->ops.exit)
188                 resource->driver->ops.exit(resource);
189
190         unset_resource_attr_interest(resource, RESOURCE_ATTR_MASK);
191
192         do_delete_resource(resource);
193 }
194
195 static int clear_sign_bit(unsigned int val)
196 {
197         return (int)((val << 1) >> 1);
198 }
199
200 void init_resource_id(void)
201 {
202         int val;
203         struct timeval tv;
204
205         /*
206          * Initial g_resource_id is set by a combination of
207          * tv_sec and tv_usec values of gettimeofday().
208          * It ensures that PASS assigns a unique resource id
209          * for each create_resource request.
210          *
211          * Even PASS is restarted, a newly initialized value
212          * of g_resource_id reflects the current value of
213          * gettimeofday(). Thus, the uniqueness in resource
214          * id is kept unless the number of created resources
215          * crosses the time consumed (in msecs) before
216          * restarted.
217          */
218         gettimeofday(&tv, NULL);
219         val = tv.tv_sec * 1000 + tv.tv_usec / 1000;
220         g_resource_id = clear_sign_bit(val);
221 }
222
223 struct resource *create_resource(int resource_type)
224 {
225         const struct resource_driver *driver = NULL;
226         struct resource *resource = NULL;
227         int i, ret;
228
229         driver = find_resource_driver(resource_type);
230         if (!driver) {
231                 _E("failed to find resource driver, res:type(%d)\n",
232                                                 resource_type);
233                 return NULL;
234         }
235
236         resource = calloc(1, sizeof(*resource));
237         if (!resource)
238                 return NULL;
239
240         resource->id = clear_sign_bit(
241                         (unsigned int)__sync_fetch_and_add(&g_resource_id, 1));
242         resource->type = resource_type;
243         resource->name = g_strdup(driver->name);
244         resource->driver = driver;
245         resource->num_attrs = driver->num_attrs;
246         resource->attrs = driver->attrs;
247         resource->attrs_value = calloc(resource->num_attrs,
248                                         sizeof(*resource->attrs_value));
249         if (!resource->attrs_value) {
250                 do_delete_resource(resource);
251                 return NULL;
252         }
253
254         for (i = 0; i < resource->num_attrs; i++)
255                 resource->attrs_value[i].type = driver->attrs[i].type;
256
257         resource->ctrls = driver->ctrls;
258         resource->num_ctrls = driver->num_ctrls;
259
260         if (driver->ops.init) {
261                 ret = driver->ops.init(resource);
262                 if (ret < 0) {
263                         _E("failed to initialize resource driver, res:type(%s)id(%d)\n",
264                                                 resource->name, resource->id);
265                         do_delete_resource(resource);
266                         return NULL;
267                 }
268         }
269
270         return resource;
271 }
272
273 int set_resource_control(struct resource *resource, u_int64_t ctrl_id, const void *data)
274 {
275         const struct resource_control *ctrl;
276         int ctrl_index = RESOURCE_CTRL_INDEX(ctrl_id);
277         int ret;
278
279         if (!resource || ctrl_index < 0 || ctrl_index >= resource->num_ctrls) {
280                 _E("Invalid parameter\n");
281                 return -EINVAL;
282         }
283
284         ctrl = &resource->ctrls[ctrl_index];
285         if (!ctrl->ops.set)
286                 return -ENOTSUP;
287
288         ret = ctrl->ops.set(resource, ctrl, data);
289         if (ret < 0)
290                 return ret;
291
292         return 0;
293 }
294
295 const char *get_resource_control_name(struct resource *resource, u_int64_t ctrl_id)
296 {
297         const struct resource_control *ctrl;
298         int ctrl_index = RESOURCE_CTRL_INDEX(ctrl_id);
299
300         if (!resource || ctrl_index < 0 || ctrl_index >= resource->num_ctrls) {
301                 _E("Invalid parameter\n");
302                 return NULL;
303         }
304
305         ctrl = &resource->ctrls[ctrl_index];
306
307         return ctrl->name;
308 }
309
310 static int update_resource_attr(struct resource *resource, u_int64_t attr_id)
311 {
312         int attr_index = RESOURCE_ATTR_INDEX(attr_id);
313         const struct resource_attribute *attr = NULL;
314         struct resource_attribute_value *attr_value = NULL;
315         int ret;
316
317         if (!resource || attr_index < 0 || attr_index >= resource->num_attrs) {
318                 _E("Invalid parameter\n");
319                 return -EINVAL;
320         }
321
322         attr = &resource->attrs[attr_index];
323
324         if (!attr->ops.get) {
325                 _E("don't support get ops of resource attribute value, res:type(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
326                                 resource->name, resource->id,
327                                 attr->name, attr_id);
328                 return -EINVAL;
329         }
330
331         attr_value = &resource->attrs_value[attr_index];
332
333         ret = attr->ops.get(resource, attr, attr_value->data);
334         if (ret < 0) {
335                 _E("failed to get resource attribute value, res:type(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
336                                 resource->name, resource->id,
337                                 attr->name, attr_id);
338                 return ret;
339         }
340
341         return 0;
342 }
343
344 int update_resource_attrs(struct resource *resource)
345 {
346         int i, ret;
347
348         if (!resource || !resource->type)
349                 return -EINVAL;
350
351         resource->ts_start = get_time_now();
352
353         if (resource->driver && resource->driver->ops.prepare_update) {
354                 ret = resource->driver->ops.prepare_update(resource);
355                 if (ret < 0) {
356                         _E("failed to prepare_update resource driver, res:type(%s)id(%d)\n",
357                                         resource->name, resource->id);
358                         return ret;
359                 }
360         }
361
362         for (i = 0; i < resource->num_attrs; i++) {
363                 if (!(resource->attrs[i].id & resource->attr_interest))
364                         continue;
365                 ret = update_resource_attr(resource, resource->attrs[i].id);
366                 if (ret < 0) {
367                         _E("failed to update resource attribute, res:type(%s)id(%d) | attr:name(%s)id(%"PRId64")\n",
368                                 resource->name, resource->id,
369                                 resource->attrs[i].name, resource->attrs[i].id);
370                 }
371         }
372
373         resource->ts_end = get_time_now();
374
375         return 0;
376 }
377
378 const struct resource_attribute *
379 get_resource_attr(struct resource *resource, u_int64_t attr_id)
380 {
381         int attr_index = RESOURCE_ATTR_INDEX(attr_id);
382
383         if (!resource || attr_index < 0 || attr_index >= resource->num_attrs) {
384                 _E("Invalid parameter\n");
385                 return NULL;
386         }
387
388         return &resource->attrs[attr_index];
389 }
390
391 struct resource_attribute_value *
392 get_resource_attr_value(struct resource *resource, u_int64_t attr_id)
393 {
394         int attr_index = RESOURCE_ATTR_INDEX(attr_id);
395
396         if (!resource || attr_index < 0 || attr_index >= resource->num_attrs) {
397                 _E("Invalid parameter\n");
398                 return NULL;
399         }
400
401         return &resource->attrs_value[attr_index];
402 }
403
404 int is_resource_attr_supported(struct resource *resource, u_int64_t attr_id, bool *supported)
405 {
406         const struct resource_attribute *attr = NULL;
407         int attr_index = RESOURCE_ATTR_INDEX(attr_id);
408         int ret;
409         bool is_supported = false;
410
411         if (!resource || attr_index < 0 || attr_index >= resource->num_attrs) {
412                 _E("Invalid parameter\n");
413                 return -EINVAL;
414         }
415
416         attr = &resource->attrs[attr_index];
417
418         if (attr->id & resource->attr_supported) {
419                 is_supported = true;
420         } else if (attr->ops.is_supported) {
421                 is_supported = attr->ops.is_supported(resource, attr);
422         } else if (attr->ops.get) {
423                 /*
424                  * Optionally, if .is_supported ops is not implemented,
425                  * use .get ops in order to check whether the resource attribute
426                  * is supported or not.
427                  */
428                 char data[BUFF_MAX] = {0, };
429
430                 ret = attr->ops.get(resource, attr, (void *)data);
431                 is_supported = (ret < 0) ? false :  true;
432         }
433
434         if (is_supported)
435                 resource->attr_supported |= attr->id;
436
437         *supported = is_supported;
438
439         return 0;
440 }
441
442 static bool check_attr_validate(struct resource *resource, u_int64_t attr_id, int type)
443 {
444         const struct resource_attribute *attr = get_resource_attr(resource, attr_id);
445
446         if (!attr) {
447                 _E("Invalid parameter\n");
448                 return false;
449         }
450
451         if (attr->type != type) {
452                 _E("Invalid data type(%d), res:type(%s)id(%d) | attr:name(%s)id(%"PRId64",%d)\n",
453                                 type,
454                                 resource->name, resource->id,
455                                 attr->name, attr->id, attr->type);
456                 return false;
457         }
458
459         if (!(attr->id & resource->attr_interest)) {
460                 _E("Invalid interest state, res:type(%s)id(%d) | attr:name(%s)id(%"PRId64")type(%d)\n",
461                                 resource->name, resource->id,
462                                 attr->name, attr->id, attr->type);
463                 return false;
464         }
465
466         return true;
467 }
468
469 static json_object *_get_resource_attr_json(const struct resource_attribute *attr,
470                                              const struct resource_attribute_value *attr_value)
471 {
472         json_object *jobj_attr, *jobj_attr_name, *jobj_attr_type, *jobj_attr_value, *jobj_temp;
473         struct array_value *array;
474         int i;
475
476         switch (attr->type) {
477         case DATA_TYPE_INT:
478                 jobj_attr_value = json_object_new_int(*((int32_t *)attr_value->data));
479                 break;
480         case DATA_TYPE_UINT:
481                 jobj_attr_value = json_object_new_int(*((u_int32_t *)attr_value->data));
482                 break;
483         case DATA_TYPE_INT64:
484                 jobj_attr_value = json_object_new_int64(*((int64_t *)attr_value->data));
485                 break;
486         case DATA_TYPE_UINT64:
487                 jobj_attr_value = json_object_new_uint64(*((u_int64_t *)attr_value->data));
488                 break;
489         case DATA_TYPE_DOUBLE:
490                 jobj_attr_value = json_object_new_double(*((double *)attr_value->data));
491                 break;
492         case DATA_TYPE_STRING:
493                 jobj_attr_value = json_object_new_string((char *)attr_value->data);
494                 break;
495         case DATA_TYPE_ARRAY:
496                 array = attr_value->data;
497
498                 jobj_attr_value = json_object_new_array();
499
500                 switch (array->type) {
501                 case DATA_TYPE_INT:
502                         for (i = 0; i < array->length; i++) {
503                                 int32_t *item = array->data;
504
505                                 jobj_temp = json_object_new_int(item[i]);
506                                 json_object_array_add(jobj_attr_value, jobj_temp);
507                         }
508                         break;
509                 case DATA_TYPE_UINT:
510                         for (i = 0; i < array->length; i++) {
511                                 u_int32_t *item = array->data;
512
513                                 jobj_temp = json_object_new_int(item[i]);
514                                 json_object_array_add(jobj_attr_value, jobj_temp);
515                         }
516                         break;
517                 case DATA_TYPE_INT64:
518                         for (i = 0; i < array->length; i++) {
519                                 int64_t *item = array->data;
520
521                                 jobj_temp = json_object_new_int64(item[i]);
522                                 json_object_array_add(jobj_attr_value, jobj_temp);
523                         }
524                         break;
525                 case DATA_TYPE_UINT64:
526                         for (i = 0; i < array->length; i++) {
527                                 u_int64_t *item = array->data;
528
529                                 jobj_temp = json_object_new_uint64(item[i]);
530                                 json_object_array_add(jobj_attr_value, jobj_temp);
531                         }
532                         break;
533                 case DATA_TYPE_DOUBLE:
534                         for (i = 0; i < array->length; i++) {
535                                 double *item = array->data;
536
537                                 jobj_temp = json_object_new_double(item[i]);
538                                 json_object_array_add(jobj_attr_value, jobj_temp);
539                         }
540                         break;
541                 case DATA_TYPE_STRING:
542                         for (i = 0; i < array->length; i++) {
543                                 char **item = array->data;
544
545                                 jobj_temp = json_object_new_string(item[i]);
546                                 json_object_array_add(jobj_attr_value, jobj_temp);
547                         }
548                         break;
549                 default:
550                         _E("wrong attribute data type in array\n");
551                         json_object_put(jobj_attr_value);
552                         jobj_attr_value = json_object_new_null();
553                 }
554                 break;
555         default:
556                 _E("wrong attribute data type\n");
557                 jobj_attr_value = json_object_new_null();
558         }
559         jobj_attr = json_object_new_object();
560
561         jobj_attr_name = json_object_new_string(attr->name);
562         /*
563          * Since actually JSON format has no data type limitation itself, in many
564          * cases except converting JSON into json-c, type is not required. So,
565          * for the case of converting JSON generated here to json-c object again
566          * json_type is stored in each attributes.
567          */
568         jobj_attr_type = json_object_new_int(json_object_get_type(jobj_attr_value));
569
570         json_object_object_add(jobj_attr, "name", jobj_attr_name);
571         json_object_object_add(jobj_attr, "json_type", jobj_attr_type);
572         json_object_object_add(jobj_attr, "value", jobj_attr_value);
573
574         return jobj_attr;
575 }
576
577 static void _put_resource_attr_json(json_object *jobj_attr)
578 {
579         json_object *jobj_attr_value;
580
581         json_object_object_del(jobj_attr, "name");
582         json_object_object_del(jobj_attr, "json_type");
583
584         if (json_object_object_get_ex(jobj_attr, "value", &jobj_attr_value) &&
585                         json_object_is_type(jobj_attr_value, json_type_array))
586                 json_object_array_del_idx(jobj_attr_value, 0,
587                                           json_object_array_length(jobj_attr_value));
588
589         json_object_object_del(jobj_attr, "value");
590 }
591
592 int get_resource_attrs_json(struct resource *resource, char **json_string)
593 {
594         json_object *jobj_root, *jobj_res_name, *jobj_res_type, *jobj_res_attrs, *jobj_attr;
595         json_object *jobj_res_ts, *jobj_ts_start, *jobj_ts_end;
596         const struct resource_attribute *attr;
597         const struct resource_attribute_value *attr_value;
598         int i;
599
600         if (!resource || !resource->type)
601                 return -EINVAL;
602
603         jobj_root = json_object_new_object();
604
605         jobj_res_name = json_object_new_string(resource->name);
606         jobj_res_type = json_object_new_int(resource->type);
607         jobj_res_attrs = json_object_new_array();
608
609         for (i = 0; i < resource->num_attrs; i++) {
610                 if (!(resource->attrs[i].id & resource->attr_interest))
611                         continue;
612
613                 attr = &resource->attrs[i];
614                 attr_value = &resource->attrs_value[i];
615
616                 jobj_attr = _get_resource_attr_json(attr, attr_value);
617
618                 json_object_array_add(jobj_res_attrs, jobj_attr);
619         }
620
621         jobj_res_ts = json_object_new_object();
622         jobj_ts_start = json_object_new_int64(resource->ts_start);
623         jobj_ts_end = json_object_new_int64(resource->ts_end);
624
625         json_object_object_add(jobj_res_ts, "start", jobj_ts_start);
626         json_object_object_add(jobj_res_ts, "end", jobj_ts_end);
627
628         json_object_object_add(jobj_root, "res_name", jobj_res_name);
629         json_object_object_add(jobj_root, "res_type", jobj_res_type);
630         json_object_object_add(jobj_root, "res_attrs", jobj_res_attrs);
631         json_object_object_add(jobj_root, "res_ts", jobj_res_ts);
632
633         *json_string = strdup(json_object_to_json_string(jobj_root));
634
635         json_object_object_del(jobj_res_ts, "end");
636         json_object_object_del(jobj_res_ts, "start");
637
638         for (i = 0; i < json_object_array_length(jobj_res_attrs); i++) {
639                 jobj_attr = json_object_array_get_idx(jobj_res_attrs, i);
640                 _put_resource_attr_json(jobj_attr);
641         }
642         json_object_array_del_idx(jobj_res_attrs, 0, json_object_array_length(jobj_res_attrs));
643
644         json_object_object_del(jobj_root, "res_ts");
645         json_object_object_del(jobj_root, "res_attrs");
646         json_object_object_del(jobj_root, "res_type");
647         json_object_object_del(jobj_root, "res_name");
648         json_object_put(jobj_root);
649
650         return 0;
651 }
652
653 int get_resource_attr_json(struct resource *resource, u_int64_t attr_id, char **json_string)
654 {
655         const struct resource_attribute *attr;
656         const struct resource_attribute_value *attr_value;
657         json_object *jobj_attr;
658
659         attr = get_resource_attr(resource, attr_id);
660         attr_value = get_resource_attr_value(resource, attr_id);
661
662         if (!attr || !attr_value)
663                 return -EINVAL;
664
665         jobj_attr = _get_resource_attr_json(attr, attr_value);
666
667         *json_string = strdup(json_object_to_json_string(jobj_attr));
668
669         _put_resource_attr_json(jobj_attr);
670
671         return 0;
672 }
673
674 static json_object *get_resource_driver_json(const struct resource_driver *driver)
675 {
676         json_object *jobj_drv, *jobj_drv_name, *jobj_drv_type;
677         json_object *jobj_drv_attrs_array, *jobj_drv_attr, *jobj_drv_ctrls_array, *jobj_drv_ctrl;
678         json_object *jobj_drv_attr_name, *jobj_drv_attr_type, *jobj_drv_attr_id;
679         json_object *jobj_drv_ctrl_name, *jobj_drv_ctrl_id;
680         const struct resource_attribute *attr;
681         const struct resource_control *ctrl;
682         int i;
683
684         jobj_drv = json_object_new_object();
685
686         jobj_drv_name = json_object_new_string(driver->name);
687         jobj_drv_type = json_object_new_int(driver->type);
688
689         jobj_drv_attrs_array = json_object_new_array();
690
691         for (i = 0; i < driver->num_attrs; i++) {
692                 attr = &driver->attrs[i];
693
694                 jobj_drv_attr = json_object_new_object();
695
696                 jobj_drv_attr_name = json_object_new_string(attr->name);
697                 jobj_drv_attr_type = json_object_new_int(attr->type);
698                 jobj_drv_attr_id = json_object_new_uint64(attr->id);
699
700                 json_object_object_add(jobj_drv_attr, "name", jobj_drv_attr_name);
701                 json_object_object_add(jobj_drv_attr, "type", jobj_drv_attr_type);
702                 json_object_object_add(jobj_drv_attr, "id", jobj_drv_attr_id);
703
704                 json_object_array_add(jobj_drv_attrs_array, jobj_drv_attr);
705         }
706
707         jobj_drv_ctrls_array = json_object_new_array();
708
709         for (i = 0; i < driver->num_ctrls; i++) {
710                 ctrl = &driver->ctrls[i];
711
712                 jobj_drv_ctrl = json_object_new_object();
713
714                 jobj_drv_ctrl_name = json_object_new_string(ctrl->name);
715                 jobj_drv_ctrl_id = json_object_new_uint64(ctrl->id);
716
717                 json_object_object_add(jobj_drv_ctrl, "name", jobj_drv_ctrl_name);
718                 json_object_object_add(jobj_drv_ctrl, "id", jobj_drv_ctrl_id);
719
720                 json_object_array_add(jobj_drv_ctrls_array, jobj_drv_ctrl);
721         }
722
723         json_object_object_add(jobj_drv, "name", jobj_drv_name);
724         json_object_object_add(jobj_drv, "type", jobj_drv_type);
725         json_object_object_add(jobj_drv, "attrs", jobj_drv_attrs_array);
726         json_object_object_add(jobj_drv, "ctrls", jobj_drv_ctrls_array);
727
728         return jobj_drv;
729 }
730
731 void put_resource_driver_json(json_object *jobj_drv)
732 {
733         json_object *jobj_array, *jobj_obj;
734         int i;
735
736         if (json_object_object_get_ex(jobj_drv, "ctrls", &jobj_array)) {
737                 for (i = 0; i < json_object_array_length(jobj_array); i++) {
738                         jobj_obj = json_object_array_get_idx(jobj_array, i);
739
740                         json_object_object_del(jobj_obj, "id");
741                         json_object_object_del(jobj_obj, "name");
742                 }
743                 json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array));
744         }
745
746         if (json_object_object_get_ex(jobj_drv, "attrs", &jobj_array)) {
747                 for (i = 0; i < json_object_array_length(jobj_array); i++) {
748                         jobj_obj = json_object_array_get_idx(jobj_array, i);
749
750                         json_object_object_del(jobj_obj, "id");
751                         json_object_object_del(jobj_obj, "type");
752                         json_object_object_del(jobj_obj, "name");
753                 }
754                 json_object_array_del_idx(jobj_array, 0, json_object_array_length(jobj_array));
755         }
756
757         json_object_object_del(jobj_drv, "ctrls");
758         json_object_object_del(jobj_drv, "attrs");
759         json_object_object_del(jobj_drv, "type");
760         json_object_object_del(jobj_drv, "name");
761 }
762
763 int get_resource_list_json(char **json_string)
764 {
765         const struct resource_driver *driver;
766         json_object *jobj_root, *jobj_drvs_array, *jobj_drv;
767         int i;
768
769         jobj_root = json_object_new_object();
770         jobj_drvs_array = json_object_new_array();
771
772         for (i = 0; i < g_list_length(g_resource_driver_head); i++) {
773                 driver = g_list_nth(g_list_first(g_resource_driver_head), i)->data;
774
775                 jobj_drv = get_resource_driver_json(driver);
776                 json_object_array_add(jobj_drvs_array, jobj_drv);
777         }
778
779         json_object_object_add(jobj_root, "resources", jobj_drvs_array);
780
781         *json_string = strdup(json_object_to_json_string(jobj_root));
782
783         for (i = 0; i < json_object_array_length(jobj_drvs_array); i++) {
784                 jobj_drv = json_object_array_get_idx(jobj_drvs_array, i);
785
786                 put_resource_driver_json(jobj_drv);
787         }
788         json_object_array_del_idx(jobj_drvs_array, 0, json_object_array_length(jobj_drvs_array));
789
790         json_object_object_del(jobj_root, "resources");
791         json_object_put(jobj_root);
792
793         return 0;
794 }
795
796 int get_resource_attr_int(struct resource *resource, u_int64_t attr_id, int32_t *data)
797 {
798         struct resource_attribute_value *attr_value = NULL;
799
800         if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT))
801                 return -EINVAL;
802
803         attr_value = get_resource_attr_value(resource, attr_id);
804         if (!attr_value)
805                 return -EINVAL;
806
807         *data = *((int32_t *)attr_value->data);
808
809         return 0;
810 }
811
812 int get_resource_attr_int64(struct resource *resource, u_int64_t attr_id, int64_t *data)
813 {
814         struct resource_attribute_value *attr_value = NULL;
815
816         if (!check_attr_validate(resource, attr_id, DATA_TYPE_INT64))
817                 return -EINVAL;
818
819         attr_value = get_resource_attr_value(resource, attr_id);
820         if (!attr_value)
821                 return -EINVAL;
822
823         *data = *((int64_t *)attr_value->data);
824
825         return 0;
826 }
827
828 int get_resource_attr_uint(struct resource *resource, u_int64_t attr_id, u_int32_t *data)
829 {
830         struct resource_attribute_value *attr_value = NULL;
831
832         if (!check_attr_validate(resource, attr_id, DATA_TYPE_UINT))
833                 return -EINVAL;
834
835         attr_value = get_resource_attr_value(resource, attr_id);
836         if (!attr_value)
837                 return -EINVAL;
838
839         *data = *((u_int32_t *)attr_value->data);
840
841         return 0;
842 }
843
844 int get_resource_attr_uint64(struct resource *resource, u_int64_t attr_id, u_int64_t *data)
845 {
846         struct resource_attribute_value *attr_value = NULL;
847
848         if (!check_attr_validate(resource, attr_id, DATA_TYPE_UINT64))
849                 return -EINVAL;
850
851         attr_value = get_resource_attr_value(resource, attr_id);
852         if (!attr_value)
853                 return -EINVAL;
854
855         *data = *((u_int64_t *)attr_value->data);
856
857         return 0;
858 }
859
860 int get_resource_attr_double(struct resource *resource, u_int64_t attr_id, double *data)
861 {
862         struct resource_attribute_value *attr_value = NULL;
863
864         if (!check_attr_validate(resource, attr_id, DATA_TYPE_DOUBLE))
865                 return -EINVAL;
866
867         attr_value = get_resource_attr_value(resource, attr_id);
868         if (!attr_value)
869                 return -EINVAL;
870
871         *data = *((double *)attr_value->data);
872
873         return 0;
874 }
875
876 int get_resource_attr_string(struct resource *resource, u_int64_t attr_id, char *data)
877 {
878         struct resource_attribute_value *attr_value = NULL;
879
880         if (!check_attr_validate(resource, attr_id, DATA_TYPE_STRING)) {
881                 _E("Invalid parameter\n");
882                 return -EINVAL;
883         }
884
885         attr_value = get_resource_attr_value(resource, attr_id);
886         if (!attr_value) {
887                 _E("failed to get attribute value\n");
888                 return -EINVAL;
889         }
890
891         strncpy(data, (char *)attr_value->data, BUFF_MAX);
892
893         return 0;
894 }
895
896 int get_resource_attr_array(struct resource *resource, u_int64_t attr_id, struct array_value **data)
897 {
898         struct resource_attribute_value *attr_value = NULL;
899
900         if (!check_attr_validate(resource, attr_id, DATA_TYPE_ARRAY))
901                 return -EINVAL;
902
903         attr_value = get_resource_attr_value(resource, attr_id);
904         if (!attr_value)
905                 return -EINVAL;
906
907         *data = (struct array_value *)attr_value->data;
908
909         return 0;
910 }
911
912 int get_resource_attr_ptr(struct resource *resource, u_int64_t attr_id, void **data)
913 {
914         struct resource_attribute_value *attr_value = NULL;
915
916         if (!check_attr_validate(resource, attr_id, DATA_TYPE_PTR))
917                 return -EINVAL;
918
919         attr_value = get_resource_attr_value(resource, attr_id);
920         if (!attr_value)
921                 return -EINVAL;
922
923         *data = attr_value->data;
924
925         return 0;
926 }
927
928 int set_resource_attr_interest(struct resource *resource, u_int64_t interest_mask)
929 {
930         struct resource_attribute_value *attr_value;
931         int i, ret;
932         bool supported;
933
934         if (!resource)
935                 return -EINVAL;
936
937         for (i = 0; i < resource->num_attrs; i++) {
938                 if (!(resource->attrs[i].id & interest_mask))
939                         continue;
940
941                 ret = is_resource_attr_supported(resource, resource->attrs[i].id,
942                                                 &supported);
943                 if (ret < 0) {
944                         goto err;
945                 } else if (!supported){
946                         ret = -ENOTSUP;
947                         goto err;
948                 }
949
950                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
951                 if (!attr_value) {
952                         _E("failed to get attribute value, res:type(%s) | attr:name(%s)",
953                                         resource->name, resource->attrs[i].name);
954                         ret = -EINVAL;
955                         goto err;
956                 }
957
958                 /*
959                  * In resource monitor, each resource has a lot of attributes, but
960                  * only updated attributes are selected by clients on demand. So,
961                  * instead of allocating memory at the resource creation, allocate
962                  * at the set interest.
963                  */
964                 if (!attr_value->data) {
965                         switch (attr_value->type) {
966                         case DATA_TYPE_INT:
967                                 attr_value->data = calloc(1, sizeof(int32_t));
968                                 break;
969                         case DATA_TYPE_INT64:
970                                 attr_value->data = calloc(1, sizeof(int64_t));
971                                 break;
972                         case DATA_TYPE_UINT:
973                                 attr_value->data = calloc(1, sizeof(u_int32_t));
974                                 break;
975                         case DATA_TYPE_UINT64:
976                                 attr_value->data = calloc(1, sizeof(u_int64_t));
977                                 break;
978                         case DATA_TYPE_DOUBLE:
979                                 attr_value->data = calloc(1, sizeof(double));
980                                 break;
981                         case DATA_TYPE_STRING:
982                                 attr_value->data = calloc(BUFF_MAX, sizeof(char));
983                                 break;
984                         case DATA_TYPE_ARRAY:
985                                 attr_value->data = calloc(1, sizeof(struct array_value));
986                                 break;
987                         default:
988                                 _E("Not supported data type(%d)", attr_value->type);
989                                 ret = -EINVAL;
990                                 goto err;
991                         }
992
993                         if (!attr_value->data) {
994                                 _E("failed to allocate attr_value memory, res:type(%s) | attr:name(%s)",
995                                         resource->name, resource->attrs[i].name);
996                                 ret = -ENOMEM;
997                                 goto err;
998                         }
999                 }
1000         }
1001
1002         resource->attr_interest |= interest_mask;
1003
1004         return 0;
1005
1006 err:
1007         for (; i >= 0;  i--) {
1008                 if (!(resource->attrs[i].id & interest_mask))
1009                         continue;
1010
1011                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
1012                 if (!attr_value)
1013                         continue;
1014
1015                 if (attr_value->data) {
1016                         free(attr_value->data);
1017                         attr_value->data = NULL;
1018                 }
1019         }
1020
1021         return ret;
1022 }
1023
1024 int unset_resource_attr_interest(struct resource *resource, u_int64_t interest_mask)
1025 {
1026         struct resource_attribute_value *attr_value;
1027         int i;
1028
1029         if (!resource)
1030                 return -EINVAL;
1031
1032         if (!is_resource_attr_interested(resource, interest_mask))
1033                 return -EINVAL;
1034
1035         for (i = 0; i < resource->num_attrs; i++) {
1036                 if (!(resource->attrs[i].id & interest_mask))
1037                         continue;
1038
1039                 attr_value = get_resource_attr_value(resource, resource->attrs[i].id);
1040                 if (!attr_value) {
1041                         _E("failed to get attribute value, res:type(%s) | attr:name(%s)",
1042                                         resource->name, resource->attrs[i].name);
1043                         return -EINVAL;
1044                 }
1045
1046                 if (attr_value->data) {
1047                         switch (attr_value->type) {
1048                         case DATA_TYPE_ARRAY:
1049                         {
1050                                 struct array_value *array = attr_value->data;
1051
1052                                 if (array->data) {
1053                                         free(array->data);
1054                                         array->data = NULL;
1055                                 }
1056                                 /* fall through */
1057                         }
1058                         case DATA_TYPE_INT:
1059                         case DATA_TYPE_INT64:
1060                         case DATA_TYPE_UINT:
1061                         case DATA_TYPE_UINT64:
1062                         case DATA_TYPE_DOUBLE:
1063                         case DATA_TYPE_STRING:
1064                                 free(attr_value->data);
1065                                 attr_value->data = NULL;
1066                                 break;
1067                         default:
1068                                 _E("Not supported data type(%d)", attr_value->type);
1069                                 return -EINVAL;
1070                         }
1071                 }
1072         }
1073
1074         resource->attr_interest &= ~interest_mask;
1075
1076         return 0;
1077 }
1078
1079 bool is_resource_attr_interested(struct resource *resource, u_int64_t interest_mask)
1080 {
1081         if (!resource)
1082                 return false;
1083
1084         if (resource->attr_interest != (resource->attr_interest | interest_mask))
1085                 return false;
1086
1087         return true;
1088 }
1089
1090 const char *get_resource_attr_name(struct resource *resource, u_int64_t attr_id)
1091 {
1092         const struct resource_attribute *attr;
1093
1094         attr = get_resource_attr(resource, attr_id);
1095         if (!attr)
1096                 return NULL;
1097
1098         return attr->name;
1099 }
1100
1101 const char *get_resource_name(struct resource *resource)
1102 {
1103         return resource ? resource->name : NULL;
1104 }
1105
1106 void *get_resource_privdata(struct resource *resource)
1107 {
1108         return resource ? resource->priv : NULL;
1109 }
1110
1111 int get_resource_id(struct resource *resource)
1112 {
1113         return resource ? resource->id : -EINVAL;
1114 }
1115
1116 int get_resource_type(struct resource *resource)
1117 {
1118         return resource ? resource->type : -EINVAL;
1119 }
1120
1121 int get_resource_ts(struct resource *resource, int64_t *ts_start, int64_t *ts_end)
1122 {
1123         if (!resource)
1124                 return -EINVAL;
1125
1126         *ts_start = resource->ts_start;
1127         *ts_end = resource->ts_end;
1128
1129         return 0;
1130 }
1131
1132 int set_resource_privdata(struct resource *resource, void *priv)
1133 {
1134         if (!resource)
1135                 return -EINVAL;
1136
1137         resource->priv = priv;
1138
1139         return 0;
1140 }