Thu Apr 28 2011 16:57:08

Asterisk developer's documentation


devicestate.h File Reference

Device state management. More...

#include "asterisk/channel.h"
Include dependency graph for devicestate.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  ast_devstate_aggregate
 You shouldn't care about the contents of this struct. More...

Typedefs

typedef enum ast_device_state(* ast_devstate_prov_cb_type )(const char *data)
 Devicestate provider call back.

Enumerations

enum  ast_device_state {
  AST_DEVICE_UNKNOWN, AST_DEVICE_NOT_INUSE, AST_DEVICE_INUSE, AST_DEVICE_BUSY,
  AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE,
  AST_DEVICE_ONHOLD, AST_DEVICE_TOTAL
}
 

Device States.

More...

Functions

enum ast_device_state ast_device_state (const char *device)
 Asks a channel for device state.
int ast_device_state_changed (const char *fmt,...)
 Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.)
int ast_device_state_changed_literal (const char *device)
 Tells Asterisk the State for Device is changed.
const char * ast_devstate2str (enum ast_device_state devstate) attribute_pure
 Find devicestate as text message for output.
void ast_devstate_aggregate_add (struct ast_devstate_aggregate *agg, enum ast_device_state state)
 Add a device state to the aggregate device state.
void ast_devstate_aggregate_init (struct ast_devstate_aggregate *agg)
 Initialize aggregate device state.
enum ast_device_state ast_devstate_aggregate_result (struct ast_devstate_aggregate *agg)
 Get the aggregate device state result.
int ast_devstate_changed (enum ast_device_state state, const char *fmt,...)
 Tells Asterisk the State for Device is changed.
int ast_devstate_changed_literal (enum ast_device_state state, const char *device)
 Tells Asterisk the State for Device is changed.
int ast_devstate_prov_add (const char *label, ast_devstate_prov_cb_type callback)
 Add device state provider.
int ast_devstate_prov_del (const char *label)
 Remove device state provider.
const char * ast_devstate_str (enum ast_device_state devstate) attribute_pure
 Convert device state to text string that is easier to parse.
enum ast_device_state ast_devstate_val (const char *val)
 Convert device state from text to integer value.
int ast_enable_distributed_devstate (void)
 Enable distributed device state processing.
enum ast_device_state ast_parse_device_state (const char *device)
 Search the Channels by Name.
enum ast_device_state ast_state_chan2dev (enum ast_channel_state chanstate)
 Convert channel state to devicestate.
const char * devstate2str (enum ast_device_state devstate) attribute_pure
 Convert device state to text string for output.

Detailed Description

Device state management.

To subscribe to device state changes, use the generic ast_event_subscribe method. For an example, see apps/app_queue.c.

Todo:
Currently, when the state of a device changes, the device state provider calls one of the functions defined here to queue an object to say that the state of a device has changed. However, this does not include the new state. Another thread processes these device state change objects and calls the device state provider's callback to figure out what the new state is. It would make a lot more sense for the new state to be included in the original function call that says the state of a device has changed. However, it will take a lot of work to change this.

Definition in file devicestate.h.


Typedef Documentation

typedef enum ast_device_state(* ast_devstate_prov_cb_type)(const char *data)

Devicestate provider call back.

Definition at line 65 of file devicestate.h.


Enumeration Type Documentation

Device States.

Note:
The order of these states may not change because they are included in Asterisk events which may be transmitted across the network to other servers.
Enumerator:
AST_DEVICE_UNKNOWN 

Device is valid but channel didn't know state

AST_DEVICE_NOT_INUSE 

Device is not used

AST_DEVICE_INUSE 

Device is in use

AST_DEVICE_BUSY 

Device is busy

AST_DEVICE_INVALID 

Device is invalid

AST_DEVICE_UNAVAILABLE 

Device is unavailable

AST_DEVICE_RINGING 

Device is ringing

AST_DEVICE_RINGINUSE 

Device is ringing *and* in use

AST_DEVICE_ONHOLD 

Device is on hold

AST_DEVICE_TOTAL 

Definition at line 51 of file devicestate.h.

                      {
   AST_DEVICE_UNKNOWN,      /*!< Device is valid but channel didn't know state */
   AST_DEVICE_NOT_INUSE,    /*!< Device is not used */
   AST_DEVICE_INUSE,        /*!< Device is in use */
   AST_DEVICE_BUSY,         /*!< Device is busy */
   AST_DEVICE_INVALID,      /*!< Device is invalid */
   AST_DEVICE_UNAVAILABLE,  /*!< Device is unavailable */
   AST_DEVICE_RINGING,      /*!< Device is ringing */
   AST_DEVICE_RINGINUSE,    /*!< Device is ringing *and* in use */
   AST_DEVICE_ONHOLD,       /*!< Device is on hold */
   AST_DEVICE_TOTAL,        /*/ Total num of device states, used for testing */
};

Function Documentation

enum ast_device_state ast_device_state ( const char *  device)

Asks a channel for device state.

Parameters:
devicelike a dial string

Asks a channel for device state, data is normally a number from a dial string used by the low level module Tries the channel device state callback if not supported search in the active channels list for the device.

Return values:
anAST_DEVICE_??? state
-1on failure

Definition at line 362 of file devicestate.c.

References _ast_device_state().

{
   /* This function is called from elsewhere in the code to find out the
    * current state of a device.  Check the cache, first. */

   return _ast_device_state(device, 1);
}
int ast_device_state_changed ( const char *  fmt,
  ... 
)

Tells Asterisk the State for Device is changed. (Accept change notification, add it to change queue.)

Parameters:
fmtdevice name like a dial string with format parameters

Asterisk polls the new extension states and calls the registered callbacks for the changed extensions

Return values:
0on success
-1on failure
Note:
This is deprecated in favor of ast_devstate_changed()
Version:
1.6.1 deprecated

Definition at line 522 of file devicestate.c.

References AST_DEVICE_UNKNOWN, ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.

{
   char buf[AST_MAX_EXTENSION];
   va_list ap;

   va_start(ap, fmt);
   vsnprintf(buf, sizeof(buf), fmt, ap);
   va_end(ap);

   return ast_devstate_changed_literal(AST_DEVICE_UNKNOWN, buf);
}
int ast_device_state_changed_literal ( const char *  device)

Tells Asterisk the State for Device is changed.

Parameters:
devicedevice name like a dial string

Asterisk polls the new extension states and calls the registered callbacks for the changed extensions

Return values:
0on success
-1on failure
Note:
This is deprecated in favor of ast_devstate_changed_literal()
Version:
1.6.1 deprecated

Definition at line 505 of file devicestate.c.

References AST_DEVICE_UNKNOWN, and ast_devstate_changed_literal().

const char* ast_devstate2str ( enum ast_device_state  devstate)

Find devicestate as text message for output.

Definition at line 209 of file devicestate.c.

Referenced by __queues_show(), do_state_change(), handle_statechange(), notify_metermaids(), page_exec(), and process_collection().

{
   return devstatestring[devstate][0];
}
void ast_devstate_aggregate_add ( struct ast_devstate_aggregate agg,
enum ast_device_state  state 
)

Add a device state to the aggregate device state.

Parameters:
[in]aggthe state object
[in]statethe state to add
Returns:
nothing
Since:
1.6.1

Definition at line 746 of file devicestate.c.

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_TOTAL, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.

Referenced by ast_extension_state2(), and process_collection().

{
   switch (state) {
   case AST_DEVICE_NOT_INUSE:
      agg->all_unknown = 0;
      agg->all_unavail = 0;
      agg->all_busy = 0;
      break;
   case AST_DEVICE_INUSE:
      agg->in_use = 1;
      agg->all_unavail = 0;
      agg->all_free = 0;
      agg->all_unknown = 0;
      break;
   case AST_DEVICE_RINGING:
      agg->ring = 1;
      agg->all_unavail = 0;
      agg->all_free = 0;
      agg->all_unknown = 0;
      break;
   case AST_DEVICE_RINGINUSE:
      agg->in_use = 1;
      agg->ring = 1;
      agg->all_unavail = 0;
      agg->all_free = 0;
      agg->all_unknown = 0;
      break;
   case AST_DEVICE_ONHOLD:
      agg->all_unknown = 0;
      agg->all_unavail = 0;
      agg->all_free = 0;
      agg->on_hold = 1;
      break;
   case AST_DEVICE_BUSY:
      agg->all_unknown = 0;
      agg->all_unavail = 0;
      agg->all_free = 0;
      agg->busy = 1;
      agg->in_use = 1;
      break;
   case AST_DEVICE_UNAVAILABLE:
      agg->all_unknown = 0;
   case AST_DEVICE_INVALID:
      agg->all_busy = 0;
      agg->all_free = 0;
      break;
   case AST_DEVICE_UNKNOWN:
      agg->all_busy = 0;
      agg->all_free = 0;
      break;
   case AST_DEVICE_TOTAL: /* not a device state, included for completeness. */
      break;
   }
}
void ast_devstate_aggregate_init ( struct ast_devstate_aggregate agg)

Initialize aggregate device state.

Parameters:
[in]aggthe state object
Returns:
nothing
Since:
1.6.1

Definition at line 736 of file devicestate.c.

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, and ast_devstate_aggregate::all_unknown.

Referenced by ast_extension_state2(), and process_collection().

{
   memset(agg, 0, sizeof(*agg));

   agg->all_unknown = 1;
   agg->all_unavail = 1;
   agg->all_busy = 1;
   agg->all_free = 1;
}
enum ast_device_state ast_devstate_aggregate_result ( struct ast_devstate_aggregate agg)

Get the aggregate device state result.

Parameters:
[in]aggthe state object
Returns:
the aggregate device state after adding some number of device states.
Since:
1.6.1

Definition at line 802 of file devicestate.c.

References ast_devstate_aggregate::all_busy, ast_devstate_aggregate::all_free, ast_devstate_aggregate::all_unavail, ast_devstate_aggregate::all_unknown, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_devstate_aggregate::busy, ast_devstate_aggregate::in_use, ast_devstate_aggregate::on_hold, and ast_devstate_aggregate::ring.

Referenced by ast_extension_state2(), and process_collection().

{
   if (agg->all_free)
      return AST_DEVICE_NOT_INUSE;
   if ((agg->in_use || agg->on_hold) && agg->ring)
      return AST_DEVICE_RINGINUSE;
   if (agg->ring)
      return AST_DEVICE_RINGING;
   if (agg->busy)
      return AST_DEVICE_BUSY;
   if (agg->in_use)
      return AST_DEVICE_INUSE;
   if (agg->on_hold)
      return AST_DEVICE_ONHOLD;
   if (agg->all_busy)
      return AST_DEVICE_BUSY;
   if (agg->all_unknown)
      return AST_DEVICE_UNKNOWN;
   if (agg->all_unavail)
      return AST_DEVICE_UNAVAILABLE;

   return AST_DEVICE_NOT_INUSE;
}
int ast_devstate_changed ( enum ast_device_state  state,
const char *  fmt,
  ... 
)

Tells Asterisk the State for Device is changed.

Parameters:
statethe new state of the device
fmtdevice name like a dial string with format parameters

The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.

Return values:
0on success
-1on failure

Definition at line 510 of file devicestate.c.

References ast_devstate_changed_literal(), AST_MAX_EXTENSION, and buf.

Referenced by __expire_registry(), __iax2_poke_noanswer(), agent_call(), agent_hangup(), agent_logoff_maintenance(), agent_read(), conf_run(), devstate_write(), expire_register(), handle_cli_devstate_change(), handle_offhook_message(), handle_onhook_message(), handle_response_peerpoke(), handle_soft_key_event_message(), handle_stimulus_message(), load_module(), login_exec(), notify_metermaids(), reg_source_db(), register_verify(), reload_agents(), sip_peer_hold(), sip_poke_noanswer(), skinny_register(), skinny_unregister(), sla_change_trunk_state(), sla_handle_hold_event(), sla_station_exec(), socket_process(), update_call_counter(), and update_registry().

{
   char buf[AST_MAX_EXTENSION];
   va_list ap;

   va_start(ap, fmt);
   vsnprintf(buf, sizeof(buf), fmt, ap);
   va_end(ap);

   return ast_devstate_changed_literal(state, buf);
}
int ast_devstate_changed_literal ( enum ast_device_state  state,
const char *  device 
)

Tells Asterisk the State for Device is changed.

Parameters:
statethe new state of the device
devicedevice name like a dial string with format parameters

The new state of the device will be sent off to any subscribers of device states. It will also be stored in the internal event cache.

Return values:
0on success
-1on failure

Definition at line 467 of file devicestate.c.

References ast_calloc, ast_cond_signal(), AST_DEVICE_UNKNOWN, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_UNLOCK, change_thread, state_change::device, devstate_event(), and do_state_change().

Referenced by ast_channel_free(), ast_device_state_changed(), ast_device_state_changed_literal(), ast_devstate_changed(), ast_setstate(), and dahdi_new().

{
   struct state_change *change;

   /* 
    * If we know the state change (how nice of the caller of this function!)
    * then we can just generate a device state event. 
    *
    * Otherwise, we do the following:
    *   - Queue an event up to another thread that the state has changed
    *   - In the processing thread, it calls the callback provided by the
    *     device state provider (which may or may not be a channel driver)
    *     to determine the state.
    *   - If the device state provider does not know the state, or this is
    *     for a channel and the channel driver does not implement a device
    *     state callback, then we will look through the channel list to
    *     see if we can determine a state based on active calls.
    *   - Once a state has been determined, a device state event is generated.
    */

   if (state != AST_DEVICE_UNKNOWN) {
      devstate_event(device, state);
   } else if (change_thread == AST_PTHREADT_NULL || !(change = ast_calloc(1, sizeof(*change) + strlen(device)))) {
      /* we could not allocate a change struct, or */
      /* there is no background thread, so process the change now */
      do_state_change(device);
   } else {
      /* queue the change */
      strcpy(change->device, device);
      AST_LIST_LOCK(&state_changes);
      AST_LIST_INSERT_TAIL(&state_changes, change, list);
      ast_cond_signal(&change_pending);
      AST_LIST_UNLOCK(&state_changes);
   }

   return 1;
}
int ast_devstate_prov_add ( const char *  label,
ast_devstate_prov_cb_type  callback 
)

Add device state provider.

Parameters:
labelto use in hint, like label:object
callbackCallback
Return values:
0success
-1failure

Definition at line 371 of file devicestate.c.

References ast_calloc, ast_copy_string(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, devstate_prov::callback, and devstate_prov::label.

Referenced by ast_features_init(), and load_module().

{
   struct devstate_prov *devprov;

   if (!callback || !(devprov = ast_calloc(1, sizeof(*devprov))))
      return -1;

   devprov->callback = callback;
   ast_copy_string(devprov->label, label, sizeof(devprov->label));

   AST_RWLIST_WRLOCK(&devstate_provs);
   AST_RWLIST_INSERT_HEAD(&devstate_provs, devprov, list);
   AST_RWLIST_UNLOCK(&devstate_provs);

   return 0;
}
int ast_devstate_prov_del ( const char *  label)

Remove device state provider.

Parameters:
labelto use in hint, like label:object
Return values:
-1on failure
0on success

Definition at line 389 of file devicestate.c.

References ast_free, AST_RWLIST_REMOVE_CURRENT, AST_RWLIST_TRAVERSE_SAFE_BEGIN, AST_RWLIST_TRAVERSE_SAFE_END, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, and devstate_prov::label.

Referenced by unload_module().

{
   struct devstate_prov *devcb;
   int res = -1;

   AST_RWLIST_WRLOCK(&devstate_provs);
   AST_RWLIST_TRAVERSE_SAFE_BEGIN(&devstate_provs, devcb, list) {
      if (!strcasecmp(devcb->label, label)) {
         AST_RWLIST_REMOVE_CURRENT(list);
         ast_free(devcb);
         res = 0;
         break;
      }
   }
   AST_RWLIST_TRAVERSE_SAFE_END;
   AST_RWLIST_UNLOCK(&devstate_provs);

   return res;
}
const char* ast_devstate_str ( enum ast_device_state  devstate)

Convert device state to text string that is easier to parse.

Parameters:
devstateCurrent device state

Definition at line 233 of file devicestate.c.

Referenced by devstate_read().

{
   return devstatestring[state][1];
}
enum ast_device_state ast_devstate_val ( const char *  val)

Convert device state from text to integer value.

Parameters:
valThe text representing the device state. Valid values are anything that comes after AST_DEVICE_ in one of the defined values.
Returns:
The AST_DEVICE_ integer value

Definition at line 238 of file devicestate.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_RINGING, AST_DEVICE_RINGINUSE, AST_DEVICE_UNAVAILABLE, and AST_DEVICE_UNKNOWN.

Referenced by custom_devstate_callback(), devstate_write(), handle_cli_devstate_change(), and load_module().

{
   if (!strcasecmp(val, "NOT_INUSE"))
      return AST_DEVICE_NOT_INUSE;
   else if (!strcasecmp(val, "INUSE"))
      return AST_DEVICE_INUSE;
   else if (!strcasecmp(val, "BUSY"))
      return AST_DEVICE_BUSY;
   else if (!strcasecmp(val, "INVALID"))
      return AST_DEVICE_INVALID;
   else if (!strcasecmp(val, "UNAVAILABLE"))
      return AST_DEVICE_UNAVAILABLE;
   else if (!strcasecmp(val, "RINGING"))
      return AST_DEVICE_RINGING;
   else if (!strcasecmp(val, "RINGINUSE"))
      return AST_DEVICE_RINGINUSE;
   else if (!strcasecmp(val, "ONHOLD"))
      return AST_DEVICE_ONHOLD;

   return AST_DEVICE_UNKNOWN;
}
int ast_enable_distributed_devstate ( void  )

Enable distributed device state processing.

By default, Asterisk assumes that device state change events will only be originating from one instance. If a module gets loaded and configured such that multiple instances of Asterisk will be sharing device state, this function should be called to enable distributed device state processing. It is off by default to save on unnecessary processing.

Return values:
0success
-1failure

Definition at line 826 of file devicestate.c.

References ast_cond_init(), AST_EVENT_DEVICE_STATE_CHANGE, AST_EVENT_IE_END, ast_event_subscribe(), ast_log(), ast_mutex_init(), ast_pthread_create_background, devstate_change_collector_cb(), devstate_collector, LOG_ERROR, and run_devstate_collector().

Referenced by add_publish_event(), and add_subscribe_event().

{
   if (devstate_collector.enabled) {
      return 0;
   }

   devstate_collector.event_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE_CHANGE,
      devstate_change_collector_cb, NULL, AST_EVENT_IE_END);

   if (!devstate_collector.event_sub) {
      ast_log(LOG_ERROR, "Failed to create subscription for the device state change collector\n");
      return -1;
   }

   ast_mutex_init(&devstate_collector.lock);
   ast_cond_init(&devstate_collector.cond, NULL);
   if (ast_pthread_create_background(&devstate_collector.thread, NULL, run_devstate_collector, NULL) < 0) {
      ast_log(LOG_ERROR, "Unable to start device state collector thread.\n");
      return -1;
   }

   devstate_collector.enabled = 1;

   return 0;
}
enum ast_device_state ast_parse_device_state ( const char *  device)

Search the Channels by Name.

Parameters:
devicelike a dial string

Search the Device in active channels by compare the channel name against the device name. Compared are only the first chars to the first '-' char.

Return values:
AST_DEVICE_UNKNOWNif no channel found
AST_DEVICE_INUSEif a channel is found

Search the Channels by Name.

Note:
find channels with the device's name in it This function is only used for channels that does not implement devicestate natively

Definition at line 265 of file devicestate.c.

References ast_channel::_state, AST_CHANNEL_NAME, ast_channel_unlock, ast_copy_string(), AST_DEVICE_INUSE, AST_DEVICE_RINGING, AST_DEVICE_UNKNOWN, ast_get_channel_by_name_prefix_locked(), AST_STATE_RINGING, chan, and match().

Referenced by _ast_device_state(), and chanavail_exec().

{
   struct ast_channel *chan;
   char match[AST_CHANNEL_NAME];
   enum ast_device_state res;

   ast_copy_string(match, device, sizeof(match)-1);
   strcat(match, "-");
   chan = ast_get_channel_by_name_prefix_locked(match, strlen(match));

   if (!chan)
      return AST_DEVICE_UNKNOWN;

   if (chan->_state == AST_STATE_RINGING)
      res = AST_DEVICE_RINGING;
   else
      res = AST_DEVICE_INUSE;
   
   ast_channel_unlock(chan);

   return res;
}
enum ast_device_state ast_state_chan2dev ( enum ast_channel_state  chanstate)

Convert channel state to devicestate.

Parameters:
chanstateCurrent channel state
Since:
1.6.1

Definition at line 220 of file devicestate.c.

References AST_DEVICE_UNKNOWN, chan, chan2dev::chan, and chan2dev::dev.

Referenced by dahdi_new().

{
   int i;
   chanstate &= 0xFFFF;
   for (i = 0; chan2dev[i].chan != -100; i++) {
      if (chan2dev[i].chan == chanstate) {
         return chan2dev[i].dev;
      }
   }
   return AST_DEVICE_UNKNOWN;
}
const char* devstate2str ( enum ast_device_state  devstate)

Convert device state to text string for output.

Parameters:
devstateCurrent device state

Definition at line 215 of file devicestate.c.

{
   return devstatestring[devstate][0];
}