Asterisk - The Open Source Telephony Project GIT-master-27fb039
Loading...
Searching...
No Matches
Functions | Variables
func_presencestate.c File Reference

Custom presence provider. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/linkedlists.h"
#include "asterisk/presencestate.h"
#include "asterisk/cli.h"
#include "asterisk/astdb.h"
#include "asterisk/app.h"
Include dependency graph for func_presencestate.c:

Go to the source code of this file.

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static enum ast_presence_state custom_presence_callback (const char *data, char **subtype, char **message)
 
static char * handle_cli_presencestate_change (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static char * handle_cli_presencestate_list (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 
static int load_module (void)
 
static int parse_data (char *data, enum ast_presence_state *state, char **subtype, char **message, char **options)
 
static int presence_read (struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
 
static int presence_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Gets or sets a presence state in the dialplan" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const char astdb_family [] = "CustomPresence"
 
static struct ast_cli_entry cli_funcpresencestate []
 
static struct ast_custom_function presence_function
 

Detailed Description

Custom presence provider.

Definition in file func_presencestate.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 887 of file func_presencestate.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 887 of file func_presencestate.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 887 of file func_presencestate.c.

◆ custom_presence_callback()

static enum ast_presence_state custom_presence_callback ( const char *  data,
char **  subtype,
char **  message 
)
static

Definition at line 251 of file func_presencestate.c.

252{
253 char buf[1301] = "";
255 char *_options;
256 char *_message;
257 char *_subtype;
258
259 if (ast_db_get(astdb_family, data, buf, sizeof(buf))) {
261 }
262
263 if (parse_data(buf, &state, &_subtype, &_message, &_options)) {
265 }
266
267 if ((strchr(_options, 'e'))) {
268 char tmp[1301];
269
270 if (ast_strlen_zero(_subtype)) {
271 *subtype = NULL;
272 } else {
273 memset(tmp, 0, sizeof(tmp));
274 ast_base64decode((unsigned char *) tmp, _subtype, sizeof(tmp) - 1);
275 *subtype = ast_strdup(tmp);
276 }
277
278 if (ast_strlen_zero(_message)) {
279 *message = NULL;
280 } else {
281 memset(tmp, 0, sizeof(tmp));
282 ast_base64decode((unsigned char *) tmp, _message, sizeof(tmp) - 1);
283 *message = ast_strdup(tmp);
284 }
285 } else {
286 *subtype = ast_strlen_zero(_subtype) ? NULL : ast_strdup(_subtype);
287 *message = ast_strlen_zero(_message) ? NULL : ast_strdup(_message);
288 }
289 return state;
290}
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition db.c:421
#define ast_strdup(str)
A wrapper for strdup()
Definition astmm.h:241
char buf[BUFSIZE]
Definition eagi_proxy.c:66
static const char astdb_family[]
static int parse_data(char *data, enum ast_presence_state *state, char **subtype, char **message, char **options)
ast_presence_state
@ AST_PRESENCE_INVALID
@ AST_PRESENCE_NOT_SET
#define NULL
Definition resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition strings.h:65
int ast_base64decode(unsigned char *dst, const char *src, int max)
Decode data from base64.
Definition utils.c:296

References ast_base64decode(), ast_db_get(), AST_PRESENCE_INVALID, AST_PRESENCE_NOT_SET, ast_strdup, ast_strlen_zero(), astdb_family, buf, NULL, and parse_data().

Referenced by load_module().

◆ handle_cli_presencestate_change()

static char * handle_cli_presencestate_change ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 369 of file func_presencestate.c.

370{
371 size_t len;
372 const char *dev, *state, *full_dev;
373 enum ast_presence_state state_val;
374 char *message;
375 char *subtype;
376 char *options;
377 char *args;
378
379 switch (cmd) {
380 case CLI_INIT:
381 e->command = "presencestate change";
382 e->usage =
383 "Usage: presencestate change <entity> <state>[,<subtype>[,message[,options]]]\n"
384 " Change a custom presence to a new state.\n"
385 " The possible values for the state are:\n"
386 "NOT_SET | UNAVAILABLE | AVAILABLE | AWAY | XA | CHAT | DND\n"
387 "Optionally, a custom subtype and message may be provided, along with any options\n"
388 "accepted by func_presencestate. If the subtype or message provided contain spaces,\n"
389 "be sure to enclose the data in quotation marks (\"\")\n"
390 "\n"
391 "Examples:\n"
392 " presencestate change CustomPresence:mystate1 AWAY\n"
393 " presencestate change CustomPresence:mystate1 AVAILABLE\n"
394 " presencestate change CustomPresence:mystate1 \"Away,upstairs,eating lunch\"\n"
395 " \n";
396 return NULL;
397 case CLI_GENERATE:
398 {
399 static const char * const cmds[] = { "NOT_SET", "UNAVAILABLE", "AVAILABLE", "AWAY",
400 "XA", "CHAT", "DND", NULL };
401
402 if (a->pos == e->args + 1) {
403 return ast_cli_complete(a->word, cmds, a->n);
404 }
405
406 return NULL;
407 }
408 }
409
410 if (a->argc != e->args + 2) {
411 return CLI_SHOWUSAGE;
412 }
413
414 len = strlen("CustomPresence:");
415 full_dev = dev = a->argv[e->args];
416 state = a->argv[e->args + 1];
417
418 if (strncasecmp(dev, "CustomPresence:", len)) {
419 ast_cli(a->fd, "The presencestate command can only be used to set 'CustomPresence:' presence state!\n");
420 return CLI_FAILURE;
421 }
422
423 dev += len;
424 if (ast_strlen_zero(dev)) {
425 return CLI_SHOWUSAGE;
426 }
427
429 if (parse_data(args, &state_val, &subtype, &message, &options)) {
430 return CLI_SHOWUSAGE;
431 }
432
433 if (state_val == AST_PRESENCE_NOT_SET) {
434 return CLI_SHOWUSAGE;
435 }
436
437 ast_cli(a->fd, "Changing %s to %s\n", dev, args);
438
440
441 ast_presence_state_changed_literal(state_val, subtype, message, full_dev);
442
443 return CLI_SUCCESS;
444}
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition db.c:335
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition astmm.h:298
#define CLI_SHOWUSAGE
Definition cli.h:45
#define CLI_SUCCESS
Definition cli.h:44
void ast_cli(int fd, const char *fmt,...)
Definition clicompat.c:6
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition main/cli.c:1823
@ CLI_INIT
Definition cli.h:152
@ CLI_GENERATE
Definition cli.h:153
#define CLI_FAILURE
Definition cli.h:46
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_presence_state_changed_literal(enum ast_presence_state state, const char *subtype, const char *message, const char *presence_provider)
Notify the world that a presence provider state changed.
static struct @519 args
int args
This gets set in ast_cli_register()
Definition cli.h:185
char * command
Definition cli.h:186
const char * usage
Definition cli.h:177
static struct test_options options
static struct test_val a

References a, ast_cli_entry::args, args, ast_cli(), ast_cli_complete(), ast_db_put(), AST_PRESENCE_NOT_SET, ast_presence_state_changed_literal(), ast_strdupa, ast_strlen_zero(), astdb_family, CLI_FAILURE, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, len(), NULL, options, parse_data(), and ast_cli_entry::usage.

◆ handle_cli_presencestate_list()

static char * handle_cli_presencestate_list ( struct ast_cli_entry e,
int  cmd,
struct ast_cli_args a 
)
static

Definition at line 298 of file func_presencestate.c.

299{
300 struct ast_db_entry *db_entry, *db_tree;
301
302 switch (cmd) {
303 case CLI_INIT:
304 e->command = "presencestate list";
305 e->usage =
306 "Usage: presencestate list\n"
307 " List all custom presence states that have been set by using\n"
308 " the PRESENCE_STATE dialplan function.\n";
309 return NULL;
310 case CLI_GENERATE:
311 return NULL;
312 }
313
314 if (a->argc != e->args) {
315 return CLI_SHOWUSAGE;
316 }
317
318 ast_cli(a->fd, "\n"
319 "---------------------------------------------------------------------\n"
320 "--- Custom Presence States ------------------------------------------\n"
321 "---------------------------------------------------------------------\n"
322 "---\n");
323
324 db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
325 if (!db_entry) {
326 ast_cli(a->fd, "No custom presence states defined\n");
327 return CLI_SUCCESS;
328 }
329 for (; db_entry; db_entry = db_entry->next) {
330 const char *object_name = strrchr(db_entry->key, '/') + 1;
331 char state_info[1301];
333 char *subtype;
334 char *message;
335 char *options;
336
337 ast_copy_string(state_info, db_entry->data, sizeof(state_info));
338 if (parse_data(state_info, &state, &subtype, &message, &options)) {
339 ast_log(LOG_WARNING, "Invalid CustomPresence entry %s encountered\n", db_entry->data);
340 continue;
341 }
342
343 if (object_name <= (const char *) 1) {
344 continue;
345 }
346 ast_cli(a->fd, "--- Name: 'CustomPresence:%s'\n"
347 " --- State: '%s'\n"
348 " --- Subtype: '%s'\n"
349 " --- Message: '%s'\n"
350 " --- Base64 Encoded: '%s'\n"
351 "---\n",
352 object_name,
354 subtype,
355 message,
356 AST_CLI_YESNO(strchr(options, 'e')));
357 }
358 ast_db_freetree(db_tree);
359 db_tree = NULL;
360
361 ast_cli(a->fd,
362 "---------------------------------------------------------------------\n"
363 "---------------------------------------------------------------------\n"
364 "\n");
365
366 return CLI_SUCCESS;
367}
struct ast_db_entry * ast_db_gettree(const char *family, const char *keytree)
Get a list of values within the astdb tree.
Definition db.c:635
void ast_db_freetree(struct ast_db_entry *entry)
Free structure created by ast_db_gettree()
Definition db.c:695
#define ast_log
Definition astobj2.c:42
#define AST_CLI_YESNO(x)
Return Yes or No depending on the argument.
Definition cli.h:71
#define LOG_WARNING
const char * ast_presence_state2str(enum ast_presence_state state)
Convert presence state to text string for output.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition strings.h:425
Definition astdb.h:31
struct ast_db_entry * next
Definition astdb.h:32
char * key
Definition astdb.h:33
char data[0]
Definition astdb.h:34

References a, ast_cli_entry::args, ast_cli(), AST_CLI_YESNO, ast_copy_string(), ast_db_freetree(), ast_db_gettree(), ast_log, ast_presence_state2str(), astdb_family, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_db_entry::data, ast_db_entry::key, LOG_WARNING, ast_db_entry::next, NULL, options, parse_data(), and ast_cli_entry::usage.

◆ load_module()

static int load_module ( void  )
static

Definition at line 845 of file func_presencestate.c.

846{
847 int res = 0;
848 struct ast_db_entry *db_entry, *db_tree;
849
850 /* Populate the presence state cache on the system with all of the currently
851 * known custom presence states. */
852 db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
853 for (; db_entry; db_entry = db_entry->next) {
854 const char *dev_name = strrchr(db_entry->key, '/') + 1;
856 char *message = NULL;
857 char *subtype = NULL;
858 if (dev_name <= (const char *) 1) {
859 continue;
860 }
861 state = custom_presence_callback(dev_name, &subtype, &message);
862 ast_presence_state_changed(state, subtype, message, "CustomPresence:%s", dev_name);
863 ast_free(subtype);
865 }
866 ast_db_freetree(db_tree);
867 db_tree = NULL;
868
872#ifdef TEST_FRAMEWORK
873 AST_TEST_REGISTER(test_valid_parse_data);
874 AST_TEST_REGISTER(test_invalid_parse_data);
875 AST_TEST_REGISTER(test_presence_state_change);
876 AST_TEST_REGISTER(test_presence_state_base64_encode);
877#endif
878
879 return res;
880}
#define ast_free(a)
Definition astmm.h:180
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition cli.h:265
static enum ast_presence_state custom_presence_callback(const char *data, char **subtype, char **message)
static struct ast_cli_entry cli_funcpresencestate[]
static struct ast_custom_function presence_function
#define ast_custom_function_register(acf)
Register a custom function.
Definition pbx.h:1562
int ast_presence_state_prov_add(const char *label, ast_presence_state_prov_cb_type callback)
Add presence state provider.
int ast_presence_state_changed(enum ast_presence_state state, const char *subtype, const char *message, const char *fmt,...)
Notify the world that a presence provider state changed.
#define AST_TEST_REGISTER(cb)
Definition test.h:127
#define ARRAY_LEN(a)
Definition utils.h:706

References ARRAY_LEN, ast_cli_register_multiple, ast_custom_function_register, ast_db_freetree(), ast_db_gettree(), ast_free, ast_presence_state_changed(), ast_presence_state_prov_add(), AST_TEST_REGISTER, astdb_family, cli_funcpresencestate, custom_presence_callback(), ast_db_entry::key, ast_db_entry::next, NULL, and presence_function.

◆ parse_data()

static int parse_data ( char *  data,
enum ast_presence_state state,
char **  subtype,
char **  message,
char **  options 
)
static

Definition at line 165 of file func_presencestate.c.

166{
167 char *state_str;
168
169 /* data syntax is state,subtype,message,options */
170 *subtype = "";
171 *message = "";
172 *options = "";
173
174 state_str = strsep(&data, ",");
175 if (ast_strlen_zero(state_str)) {
176 return -1; /* state is required */
177 }
178
179 *state = ast_presence_state_val(state_str);
180
181 /* not a valid state */
182 if (*state == AST_PRESENCE_INVALID) {
183 ast_log(LOG_WARNING, "Unknown presence state value %s\n", state_str);
184 return -1;
185 }
186
187 if (!(*subtype = strsep(&data,","))) {
188 *subtype = "";
189 return 0;
190 }
191
192 if (!(*message = strsep(&data, ","))) {
193 *message = "";
194 return 0;
195 }
196
197 if (!(*options = strsep(&data, ","))) {
198 *options = "";
199 return 0;
200 }
201
202 if (!ast_strlen_zero(*options) && !(strchr(*options, 'e'))) {
203 ast_log(LOG_NOTICE, "Invalid options '%s'\n", *options);
204 return -1;
205 }
206
207 return 0;
208}
char * strsep(char **str, const char *delims)
#define LOG_NOTICE
enum ast_presence_state ast_presence_state_val(const char *val)
Convert presence state from text to integer value.

References ast_log, AST_PRESENCE_INVALID, ast_presence_state_val(), ast_strlen_zero(), LOG_NOTICE, LOG_WARNING, options, and strsep().

Referenced by custom_presence_callback(), handle_cli_presencestate_change(), handle_cli_presencestate_list(), and presence_write().

◆ presence_read()

static int presence_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buf,
size_t  len 
)
static

Definition at line 105 of file func_presencestate.c.

106{
107 int state;
108 char *message = NULL;
109 char *subtype = NULL;
110 char *parse;
111 int base64encode = 0;
114 AST_APP_ARG(field);
116 );
117
118 if (ast_strlen_zero(data)) {
119 ast_log(LOG_WARNING, "PRESENCE_STATE reading requires an argument \n");
120 return -1;
121 }
122
123 parse = ast_strdupa(data);
124
126
127 if (ast_strlen_zero(args.provider) || ast_strlen_zero(args.field)) {
128 ast_log(LOG_WARNING, "PRESENCE_STATE reading requires both presence provider and presence field arguments. \n");
129 return -1;
130 }
131
132 state = ast_presence_state_nocache(args.provider, &subtype, &message);
134 ast_log(LOG_WARNING, "PRESENCE_STATE unknown \n");
135 return -1;
136 }
137
138 if (!(ast_strlen_zero(args.options)) && (strchr(args.options, 'e'))) {
139 base64encode = 1;
140 }
141
142 if (!ast_strlen_zero(subtype) && !strcasecmp(args.field, "subtype")) {
143 if (base64encode) {
144 ast_base64encode(buf, (unsigned char *) subtype, strlen(subtype), len);
145 } else {
146 ast_copy_string(buf, subtype, len);
147 }
148 } else if (!ast_strlen_zero(message) && !strcasecmp(args.field, "message")) {
149 if (base64encode) {
150 ast_base64encode(buf, (unsigned char *) message, strlen(message), len);
151 } else {
153 }
154
155 } else if (!strcasecmp(args.field, "value")) {
157 }
158
160 ast_free(subtype);
161
162 return 0;
163}
static struct prometheus_metrics_provider provider
Definition bridges.c:201
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
enum ast_presence_state ast_presence_state_nocache(const char *presence_provider, char **subtype, char **message)
Asks a presence state provider for the current presence state, bypassing the event cache.
int ast_base64encode(char *dst, const unsigned char *src, int srclen, int max)
Encode data in base64.
Definition utils.c:406

References args, AST_APP_ARG, ast_base64encode(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_free, ast_log, AST_PRESENCE_INVALID, ast_presence_state2str(), ast_presence_state_nocache(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), buf, len(), LOG_WARNING, NULL, options, and provider.

◆ presence_write()

static int presence_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 210 of file func_presencestate.c.

211{
212 size_t len = strlen("CustomPresence:");
213 char *tmp = data;
214 char *args = ast_strdupa(value);
216 char *options, *message, *subtype;
217
218 if (strncasecmp(data, "CustomPresence:", len)) {
219 ast_log(LOG_WARNING, "The PRESENCE_STATE function can only set CustomPresence: presence providers.\n");
220 return -1;
221 }
222 data += len;
223 if (ast_strlen_zero(data)) {
224 ast_log(LOG_WARNING, "PRESENCE_STATE function called with no custom device name!\n");
225 return -1;
226 }
227
228 if (parse_data(args, &state, &subtype, &message, &options)) {
229 ast_log(LOG_WARNING, "Invalid arguments to PRESENCE_STATE\n");
230 return -1;
231 }
232
234
235 if (strchr(options, 'e')) {
236 /* Let's decode the values before sending them to stasis, yes? */
237 char decoded_subtype[256] = { 0, };
238 char decoded_message[256] = { 0, };
239
240 ast_base64decode((unsigned char *) decoded_subtype, subtype, sizeof(decoded_subtype) -1);
241 ast_base64decode((unsigned char *) decoded_message, message, sizeof(decoded_message) -1);
242
243 ast_presence_state_changed_literal(state, decoded_subtype, decoded_message, tmp);
244 } else {
246 }
247
248 return 0;
249}
int value
Definition syslog.c:37

References args, ast_base64decode(), ast_db_put(), ast_log, ast_presence_state_changed_literal(), ast_strdupa, ast_strlen_zero(), astdb_family, len(), LOG_WARNING, options, parse_data(), and value.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 829 of file func_presencestate.c.

830{
831 int res = 0;
832
834 res |= ast_presence_state_prov_del("CustomPresence");
836#ifdef TEST_FRAMEWORK
837 AST_TEST_UNREGISTER(test_valid_parse_data);
838 AST_TEST_UNREGISTER(test_invalid_parse_data);
839 AST_TEST_UNREGISTER(test_presence_state_change);
840 AST_TEST_UNREGISTER(test_presence_state_base64_encode);
841#endif
842 return res;
843}
void ast_cli_unregister_multiple(void)
Definition ael_main.c:408
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
int ast_presence_state_prov_del(const char *label)
Remove presence state provider.
#define AST_TEST_UNREGISTER(cb)
Definition test.h:128

References ARRAY_LEN, ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_presence_state_prov_del(), AST_TEST_UNREGISTER, cli_funcpresencestate, and presence_function.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Gets or sets a presence state in the dialplan" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEVSTATE_PROVIDER, }
static

Definition at line 887 of file func_presencestate.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 887 of file func_presencestate.c.

◆ astdb_family

const char astdb_family[] = "CustomPresence"
static

◆ cli_funcpresencestate

struct ast_cli_entry cli_funcpresencestate[]
static
Initial value:
= {
{ .handler = handle_cli_presencestate_list , .summary = "List currently know custom presence states" ,},
{ .handler = handle_cli_presencestate_change , .summary = "Change a custom presence state" ,},
}
static char * handle_cli_presencestate_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_cli_presencestate_change(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

Definition at line 446 of file func_presencestate.c.

446 {
447 AST_CLI_DEFINE(handle_cli_presencestate_list, "List currently know custom presence states"),
448 AST_CLI_DEFINE(handle_cli_presencestate_change, "Change a custom presence state"),
449};
#define AST_CLI_DEFINE(fn, txt,...)
Definition cli.h:197

Referenced by load_module(), and unload_module().

◆ presence_function

struct ast_custom_function presence_function
static
Initial value:
= {
.name = "PRESENCE_STATE",
.read = presence_read,
.write = presence_write,
}
static int presence_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
static int presence_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)

Definition at line 292 of file func_presencestate.c.

292 {
293 .name = "PRESENCE_STATE",
294 .read = presence_read,
295 .write = presence_write,
296};

Referenced by load_module(), and unload_module().