diff --git a/channels/chan_brcm.c b/channels/chan_brcm.c index 42fdc769194ec2d01ecb8409b650fb7bd7d7593d..aeee77a38dddf0a3e44e847e8650a3d7b967ac74 100644 --- a/channels/chan_brcm.c +++ b/channels/chan_brcm.c @@ -84,6 +84,7 @@ static int brcm_create_conference(struct brcm_pvt *p); static int brcm_stop_conference(struct brcm_subchannel *p); static int brcm_finish_transfer(struct ast_channel *owner, struct brcm_subchannel *p, int result); static int brcm_call(struct ast_channel *ast, const char *dest, int timeout); +static int brcm_devicestate(const char *device_number); static int brcm_hangup(struct ast_channel *ast); static int brcm_getRtpStats(struct ast_channel *ast); static int brcm_answer(struct ast_channel *ast); @@ -318,7 +319,7 @@ static struct ast_format_cap *default_cap; static int load_common_settings(struct ast_config **cfg); static void load_lines_settings(struct ast_config *cfg); -static char *state2str(enum channel_state state); +static char *state2str(enum brcm_channel_state state); /* exported capabilities */ static struct ast_channel_tech brcm_tech = { @@ -334,7 +335,8 @@ static struct ast_channel_tech brcm_tech = { .getRtpStats = brcm_getRtpStats, //Channel is NOT locked .send_digit_end = brcm_senddigit_end, //Channel is NOT locked .indicate = brcm_indicate, //Channel is locked - .transfer = brcm_transfer // Channel is locked + .transfer = brcm_transfer, // Channel is locked + .devicestate = brcm_devicestate // Channel is NOT locked }; static struct brcm_channel_tech fxs_tech = { @@ -817,6 +819,68 @@ static int brcm_senddigit_end(struct ast_channel *ast, char digit, unsigned int return 0; } +/* + * This function is called by _ast_device_state() to get the state of the device + * + * @param[in] device_number the number of device in the format of 0/0, i.e. line_id/connection_id + * + * @return enum ast_device_state + */ +static int brcm_devicestate(const char *device_number) +{ + char *sep = NULL; + int chan_id, connection_id, sub_chan; + struct brcm_pvt *pvt; + + if (!device_number || strlen(device_number) < 3 || (sep = strchr(device_number, '/')) == NULL) { + goto __ret; + } + + chan_id = atoi(device_number); + connection_id = atoi(sep + 1); + if (chan_id < 0 || chan_id >= num_endpoints || connection_id < 0) { + goto __ret; + } + + pvt = brcm_get_pvt_from_lineid(iflist, chan_id); + if (!pvt) { + goto __ret; + } + + for (sub_chan = 0; sub_chan < NUM_SUBCHANNELS; sub_chan++) { + if (pvt->sub[sub_chan]->connection_id == connection_id) + break; + } + if (sub_chan >= NUM_SUBCHANNELS) { + goto __ret; + } + + ast_debug(1, "the state of sub_channel %d/%d is %s(%u)\n", chan_id, sub_chan, + state2str(pvt->sub[sub_chan]->channel_state), pvt->sub[sub_chan]->channel_state); + + switch (pvt->sub[sub_chan]->channel_state) { + case ONHOOK: return AST_DEVICE_NOT_INUSE; + case OFFHOOK: return AST_DEVICE_INUSE; + case DIALING: return AST_DEVICE_INUSE; + case CALLING: return AST_DEVICE_INUSE; + case INCALL: return AST_DEVICE_INUSE; + case ANSWER: return AST_DEVICE_INUSE; + case CALLENDED: return AST_DEVICE_NOT_INUSE; + case RINGING: return AST_DEVICE_RINGINUSE; + case CALLWAITING: return AST_DEVICE_INUSE; + case ONHOLD: return AST_DEVICE_ONHOLD; + case TRANSFERING: return AST_DEVICE_INUSE; + case RINGBACK: return AST_DEVICE_INUSE; + case AWAITONHOOK: return AST_DEVICE_UNAVAILABLE; + case ALLOCATED: return AST_DEVICE_NOT_INUSE; + default: return AST_DEVICE_UNKNOWN; + } + +__ret: + ast_debug(1, "invalid device_number %s\n", device_number); + return AST_DEVICE_UNKNOWN; +} + static int brcm_call(struct ast_channel *chan, const char *dest, int timeout) { struct brcm_pvt *p; @@ -1263,7 +1327,7 @@ static void brcm_reset_dtmf_buffer(struct brcm_pvt *p) p->dtmfbuf[p->dtmf_len] = '\0'; } -static char *state2str(enum channel_state state) +static char *state2str(enum brcm_channel_state state) { switch (state) { case ONHOOK: return "ONHOOK"; @@ -1279,6 +1343,7 @@ static char *state2str(enum channel_state state) case TRANSFERING: return "TRANSFERING"; case RINGBACK: return "RINGBACK"; case AWAITONHOOK: return "AWAITONHOOK"; + case ALLOCATED: return "ALLOCATED"; default: return "UNKNOWN"; } } diff --git a/channels/chan_brcm.h b/channels/chan_brcm.h index ebe1ed80799417cf71c6ddb579d3f30bc5cc8e93..992dbe1c7642876c85863fdf040b533b2e6fd8b1 100644 --- a/channels/chan_brcm.h +++ b/channels/chan_brcm.h @@ -35,7 +35,7 @@ #define CONT 1 #define END 2 -enum channel_state { +enum brcm_channel_state { ONHOOK, OFFHOOK, DIALING, @@ -98,7 +98,7 @@ struct brcm_subchannel { int id; struct ast_channel *owner; /* Channel we belong to, possibly NULL */ int connection_id; /* Current connection id, may be -1 */ - unsigned int channel_state; /* Channel states */ + enum brcm_channel_state channel_state; /* Channel states */ unsigned int connection_init; /* State for endpoint id connection initialization */ struct ast_frame fr; /* Frame */ unsigned int sequence_number; /* Endpoint RTP sequence number state */