1 /*
2 * Copyright (C) 2016 DENSO CORPORATION
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sublicense, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial
14 * portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26 #include "config.h"
27
28 #include <assert.h>
29 #include <string.h>
30 #include <stdlib.h>
31
32 #include <libweston/libweston.h>
33 #include <libweston/plugin-registry.h>
34
35 struct weston_plugin_api {
36 struct wl_list link; /**< in weston_compositor::plugin_api_list */
37
38 char *api_name; /**< The search key */
39 const void *vtable; /**< The function table */
40 size_t vtable_size; /**< Size of the function table in bytes */
41 };
42
43 /** Register an implementation of an API
44 *
45 * \param compositor The compositor instance.
46 * \param api_name The API name which other plugins use to find the
47 * implementation.
48 * \param vtable Pointer to the function table of the API.
49 * \param vtable_size Size of the function table in bytes.
50 * \return 0 on success, -1 on error, -2 if api_name already registered
51 *
52 * This call makes the given vtable to be reachable via
53 * weston_plugin_api_get(). Calls through the vtable may start happening
54 * as soon as the caller returns after success. Argument vtable must not be
55 * NULL. Argument api_name must be non-NULL and non-zero length.
56 *
57 * You can increase the function table size without breaking the ABI.
58 * To cater for ABI breaks, it is recommended to have api_name include a
59 * version number.
60 *
61 * A registered API cannot be unregistered. However, calls through a
62 * registered API must not be made from the compositor destroy signal handlers.
63 */
64 WL_EXPORT int
weston_plugin_api_register(struct weston_compositor * compositor,const char * api_name,const void * vtable,size_t vtable_size)65 weston_plugin_api_register(struct weston_compositor *compositor,
66 const char *api_name,
67 const void *vtable,
68 size_t vtable_size)
69 {
70 struct weston_plugin_api *wpa;
71
72 assert(api_name);
73 assert(strlen(api_name) > 0);
74 assert(vtable);
75
76 if (!api_name || !vtable || strlen(api_name) == 0)
77 return -1;
78
79 wl_list_for_each(wpa, &compositor->plugin_api_list, link)
80 if (strcmp(wpa->api_name, api_name) == 0)
81 return -2;
82
83 wpa = zalloc(sizeof(*wpa));
84 if (!wpa)
85 return -1;
86
87 wpa->api_name = strdup(api_name);
88 wpa->vtable = vtable;
89 wpa->vtable_size = vtable_size;
90
91 if (!wpa->api_name) {
92 free(wpa);
93
94 return -1;
95 }
96
97 wl_list_insert(&compositor->plugin_api_list, &wpa->link);
98 weston_log("Registered plugin API '%s' of size %zd\n",
99 wpa->api_name, wpa->vtable_size);
100
101 return 0;
102 }
103
104 /** Internal function to free registered APIs
105 *
106 * \param compositor The compositor instance.
107 */
108 void
weston_plugin_api_destroy_list(struct weston_compositor * compositor)109 weston_plugin_api_destroy_list(struct weston_compositor *compositor)
110 {
111 struct weston_plugin_api *wpa, *tmp;
112
113 wl_list_for_each_safe(wpa, tmp, &compositor->plugin_api_list, link) {
114 free(wpa->api_name);
115 wl_list_remove(&wpa->link);
116 free(wpa);
117 }
118 }
119
120 /** Fetch the implementation of an API
121 *
122 * \param compositor The compositor instance.
123 * \param api_name The name of the API to search for.
124 * \param vtable_size The expected function table size in bytes.
125 * \return Pointer to the function table, or NULL on error.
126 *
127 * Find the function table corresponding to api_name. The vtable_size here
128 * must be less or equal to the vtable_size given in the corresponding
129 * weston_plugin_api_register() call made by the implementing plugin.
130 *
131 * Calls can be made through the function table immediately. However, calls
132 * must not be made from or after the compositor destroy signal handler.
133 */
134 WL_EXPORT const void *
weston_plugin_api_get(struct weston_compositor * compositor,const char * api_name,size_t vtable_size)135 weston_plugin_api_get(struct weston_compositor *compositor,
136 const char *api_name,
137 size_t vtable_size)
138 {
139 struct weston_plugin_api *wpa;
140
141 assert(api_name);
142 if (!api_name)
143 return NULL;
144
145 wl_list_for_each(wpa, &compositor->plugin_api_list, link) {
146 if (strcmp(wpa->api_name, api_name) != 0)
147 continue;
148
149 if (vtable_size <= wpa->vtable_size)
150 return wpa->vtable;
151
152 return NULL;
153 }
154
155 return NULL;
156 }
157