00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "asterisk.h"
00032
00033 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 4 $")
00034
00035 #include <stdlib.h>
00036
00037 #include "asterisk/module.h"
00038 #include "asterisk/channel.h"
00039 #include "asterisk/pbx.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/linkedlists.h"
00042 #include "asterisk/devicestate.h"
00043 #include "asterisk/cli.h"
00044 #include "asterisk/astdb.h"
00045
00046 static const char astdb_family[] = "CustomDevstate";
00047
00048 static const char *ast_devstate_str(int state)
00049 {
00050 const char *res = "UNKNOWN";
00051
00052 switch (state) {
00053 case AST_DEVICE_UNKNOWN:
00054 break;
00055 case AST_DEVICE_NOT_INUSE:
00056 res = "NOT_INUSE";
00057 break;
00058 case AST_DEVICE_INUSE:
00059 res = "INUSE";
00060 break;
00061 case AST_DEVICE_BUSY:
00062 res = "BUSY";
00063 break;
00064 case AST_DEVICE_INVALID:
00065 res = "INVALID";
00066 break;
00067 case AST_DEVICE_UNAVAILABLE:
00068 res = "UNAVAILABLE";
00069 break;
00070 case AST_DEVICE_RINGING:
00071 res = "RINGING";
00072 break;
00073 case AST_DEVICE_RINGINUSE:
00074 res = "RINGINUSE";
00075 break;
00076 case AST_DEVICE_ONHOLD:
00077 res = "ONHOLD";
00078 break;
00079 }
00080
00081 return res;
00082 }
00083
00084 static int ast_devstate_val(const char *val)
00085 {
00086 if (!strcasecmp(val, "NOT_INUSE"))
00087 return AST_DEVICE_NOT_INUSE;
00088 else if (!strcasecmp(val, "INUSE"))
00089 return AST_DEVICE_INUSE;
00090 else if (!strcasecmp(val, "BUSY"))
00091 return AST_DEVICE_BUSY;
00092 else if (!strcasecmp(val, "INVALID"))
00093 return AST_DEVICE_INVALID;
00094 else if (!strcasecmp(val, "UNAVAILABLE"))
00095 return AST_DEVICE_UNAVAILABLE;
00096 else if (!strcasecmp(val, "RINGING"))
00097 return AST_DEVICE_RINGING;
00098 else if (!strcasecmp(val, "RINGINUSE"))
00099 return AST_DEVICE_RINGINUSE;
00100 else if (!strcasecmp(val, "ONHOLD"))
00101 return AST_DEVICE_ONHOLD;
00102
00103 return AST_DEVICE_UNKNOWN;
00104 }
00105
00106 static int devstate_read(struct ast_channel *chan, char *cmd, char *data,
00107 char *buf, size_t len)
00108 {
00109 ast_copy_string(buf, ast_devstate_str(ast_device_state(data)), len);
00110
00111 return 0;
00112 }
00113
00114 static int devstate_write(struct ast_channel *chan, char *function,
00115 char *data, const char *value)
00116 {
00117 size_t len = strlen("Custom:");
00118
00119 if (strncasecmp(data, "Custom:", len)) {
00120 ast_log(LOG_WARNING, "The DEVSTATE function can only be used to set 'Custom:' device state!\n");
00121 return -1;
00122 }
00123 data += len;
00124 if (ast_strlen_zero(data)) {
00125 ast_log(LOG_WARNING, "DEVSTATE function called with no custom device name!\n");
00126 return -1;
00127 }
00128
00129 ast_db_put(astdb_family, data, (char *) value);
00130
00131 ast_device_state_changed("Custom:%s", data);
00132
00133 return 0;
00134 }
00135
00136 static int custom_devstate_callback(const char *data)
00137 {
00138 char buf[256] = "";
00139
00140 ast_db_get(astdb_family, data, buf, sizeof(buf));
00141
00142 return ast_devstate_val(buf);
00143 }
00144
00145 static int cli_funcdevstate_list(int fd, int argc, char *argv[])
00146 {
00147 struct ast_db_entry *db_entry, *db_tree;
00148
00149 if (argc != 2)
00150 return RESULT_SHOWUSAGE;
00151
00152 ast_cli(fd, "\n"
00153 "---------------------------------------------------------------------\n"
00154 "--- Custom Device States --------------------------------------------\n"
00155 "---------------------------------------------------------------------\n"
00156 "---\n");
00157
00158 db_entry = db_tree = ast_db_gettree(astdb_family, NULL);
00159 for (; db_entry; db_entry = db_entry->next) {
00160 const char *dev_name = strrchr(db_entry->key, '/') + 1;
00161 if (dev_name <= (const char *) 1)
00162 continue;
00163 ast_cli(fd, "--- name: 'custom:%s' state: '%s'\n"
00164 "---\n", dev_name, db_entry->data);
00165 }
00166 ast_db_freetree(db_tree);
00167 db_tree = NULL;
00168
00169 ast_cli(fd,
00170 "---------------------------------------------------------------------\n"
00171 "---------------------------------------------------------------------\n"
00172 "\n");
00173
00174 return RESULT_SUCCESS;
00175 }
00176
00177 static struct ast_cli_entry cli_funcdevstate[] = {
00178 { { "funcdevstate", "list", }, cli_funcdevstate_list, NULL, NULL },
00179 };
00180
00181 static struct ast_custom_function devstate_function = {
00182 .name = "DEVSTATE",
00183 .synopsis = "Get or Set a device state",
00184 .syntax = "DEVSTATE(device)",
00185 .desc =
00186 " The DEVSTATE function can be used to retrieve the device state from any\n"
00187 "device state provider. For example:\n"
00188 " NoOp(SIP/mypeer has state ${DEVSTATE(SIP/mypeer)})\n"
00189 " NoOp(Conference number 1234 has state ${DEVSTATE(MeetMe:1234)})\n"
00190 "\n"
00191 " The DEVSTATE function can also be used to set custom device state from\n"
00192 "the dialplan. The \"Custom:\" prefix must be used. For example:\n"
00193 " Set(DEVSTATE(Custom:lamp1)=BUSY)\n"
00194 " Set(DEVSTATE(Custom:lamp2)=NOT_INUSE)\n"
00195 "You can subscribe to the status of a custom device state using a hint in\n"
00196 "the dialplan:\n"
00197 " exten => 1234,hint,Custom:lamp1\n"
00198 "\n"
00199 " The possible values for both uses of this function are:\n"
00200 "UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING\n"
00201 "RINGINUSE | ONHOLD\n",
00202 .read = devstate_read,
00203 .write = devstate_write,
00204 };
00205
00206 static int unload_module(void)
00207 {
00208 int res = 0;
00209
00210 res |= ast_custom_function_unregister(&devstate_function);
00211 ast_devstate_prov_del("Custom");
00212 ast_cli_unregister_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate));
00213
00214 return res;
00215 }
00216
00217 static int load_module(void)
00218 {
00219 int res = 0;
00220
00221 res |= ast_custom_function_register(&devstate_function);
00222 res |= ast_devstate_prov_add("Custom", custom_devstate_callback);
00223 ast_cli_register_multiple(cli_funcdevstate, ARRAY_LEN(cli_funcdevstate));
00224
00225 return res;
00226 }
00227
00228 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Gets or sets a device state in the dialplan");