44 #include <sys/socket.h> 46 #include <arpa/inet.h> 48 #include <sys/ioctl.h> 50 #ifdef HAVE_LINUX_COMPILER_H 51 #include <linux/compiler.h> 53 #include <linux/telephony.h> 55 #include <linux/version.h> 56 #include <linux/ixjuser.h> 73 #ifdef QTI_PHONEJACK_TJ_PCI 81 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x); 83 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, x); 86 #define IXJ_PHONE_RING_START(x) ioctl(p->fd, PHONE_RING_START, &x); 89 #define DEFAULT_CALLER_ID "Unknown" 90 #define PHONE_MAX_BUF 480 91 #define DEFAULT_GAIN 0x100 93 static const char tdesc[] =
"Standard Linux Telephony API Driver";
94 static const char config[] =
"phone.conf";
127 #define MODE_DIALTONE 1 128 #define MODE_IMMEDIATE 2 177 .description =
tdesc,
193 .description =
tdesc,
218 ioctl(p->
fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
220 ioctl(p->
fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
245 if (pvt && pvt->
owner == old)
273 outdigit = digit -
'0';
283 ioctl(p->
fd, IXJCTL_PSTN_SET_STATE, PSTN_ON_HOOK);
285 ioctl(p->
fd, IXJCTL_PSTN_SET_STATE, PSTN_OFF_HOOK);
294 ioctl(p->
fd, PHONE_PLAY_TONE, outdigit);
311 memset(&cid, 0,
sizeof(PHONE_CID));
312 snprintf(cid.month,
sizeof(cid.month),
"%02d",(tm.
tm_mon + 1));
313 snprintf(cid.day,
sizeof(cid.day),
"%02d", tm.
tm_mday);
314 snprintf(cid.hour,
sizeof(cid.hour),
"%02d", tm.
tm_hour);
315 snprintf(cid.min,
sizeof(cid.min),
"%02d", tm.
tm_min);
341 const char *
digit = strchr(dest,
'/');
366 if (ioctl(p->
fd, PHONE_REC_STOP))
368 if (ioctl(p->
fd, PHONE_PLAY_STOP))
370 if (ioctl(p->
fd, PHONE_RING_STOP))
372 if (ioctl(p->
fd, PHONE_CPT_STOP))
377 if (ioctl(p->
fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
382 if (ioctl(p->
fd, PHONE_HOOKSTATE)) {
383 ast_debug(1,
"Got hunghup, giving busy signal\n");
384 ioctl(p->
fd, PHONE_BUSY);
394 memset(p->
ext, 0,
sizeof(p->
ext));
408 ioctl(p->
fd, PHONE_CPT_STOP);
412 ioctl(p->
fd, PHONE_REC_STOP);
415 if (ioctl(p->
fd, PHONE_REC_CODEC, G729)) {
421 ioctl(p->
fd, PHONE_REC_STOP);
424 if (ioctl(p->
fd, PHONE_REC_CODEC, G723_63)) {
430 ioctl(p->
fd, PHONE_REC_STOP);
433 if (ioctl(p->
fd, PHONE_REC_CODEC, LINEAR16)) {
439 ioctl(p->
fd, PHONE_REC_STOP);
442 if (ioctl(p->
fd, PHONE_REC_CODEC, ULAW)) {
448 ioctl(p->
fd, PHONE_REC_STOP);
461 if (ioctl(p->
fd, PHONE_REC_START)) {
466 ioctl(p->
fd, PHONE_SET_TONE_ON_TIME, 300);
467 ioctl(p->
fd, PHONE_SET_TONE_OFF_TIME, 200);
477 if (ioctl(p->
fd, PHONE_PSTN_SET_STATE, PSTN_OFF_HOOK))
480 ast_debug(1,
"Took linejack off hook\n");
490 static char phone_2digit(
char c)
496 else if ((c < 10) && (c >= 0))
506 union telephony_exception phonee;
519 phonee.bytes = ioctl(p->
fd, PHONE_EXCEPTION);
520 if (phonee.bits.dtmf_ready) {
521 ast_debug(1,
"phone_exception(): DTMF\n");
524 digit = ioctl(p->
fd, PHONE_GET_DTMF_ASCII);
529 if (phonee.bits.hookstate) {
531 res = ioctl(p->
fd, PHONE_HOOKSTATE);
533 ast_debug(1,
"New hookstate: %d\n", res);
549 if (phonee.bits.pstn_ring)
551 if (phonee.bits.caller_id) {
554 if (phonee.bits.pstn_wink)
584 if (
errno == EAGAIN) {
596 switch(p->
buf[0] & 0x3) {
634 res = write(p->
fd, p->
obuf, frlen);
656 int length = strlen(text);
691 ioctl(p->
fd, PHONE_PLAY_STOP);
692 ioctl(p->
fd, PHONE_REC_STOP);
693 if (ioctl(p->
fd, PHONE_PLAY_CODEC, G729)) {
697 if (ioctl(p->
fd, PHONE_REC_CODEC, G729)) {
714 ioctl(p->
fd, PHONE_PLAY_STOP);
715 ioctl(p->
fd, PHONE_REC_STOP);
716 if (ioctl(p->
fd, PHONE_PLAY_CODEC, G723_63)) {
720 if (ioctl(p->
fd, PHONE_REC_CODEC, G723_63)) {
737 ioctl(p->
fd, PHONE_PLAY_STOP);
738 ioctl(p->
fd, PHONE_REC_STOP);
739 if (ioctl(p->
fd, PHONE_PLAY_CODEC, LINEAR16)) {
743 if (ioctl(p->
fd, PHONE_REC_CODEC, LINEAR16)) {
756 ioctl(p->
fd, PHONE_PLAY_STOP);
757 ioctl(p->
fd, PHONE_REC_STOP);
758 if (ioctl(p->
fd, PHONE_PLAY_CODEC, ULAW)) {
762 if (ioctl(p->
fd, PHONE_REC_CODEC, ULAW)) {
775 ioctl(p->
fd, PHONE_PLAY_STOP);
776 ioctl(p->
fd, PHONE_REC_STOP);
796 ioctl(p->
fd, PHONE_REC_DEPTH, 3);
797 ioctl(p->
fd, PHONE_PLAY_DEPTH, 3);
798 if (ioctl(p->
fd, PHONE_PLAY_START)) {
802 if (ioctl(p->
fd, PHONE_REC_START)) {
810 while(sofar < frame->datalen) {
812 expected = frame->
datalen - sofar;
813 if (maxfr < expected)
819 memcpy(tmpbuf, frame->
data.
ptr, 4);
827 #if __BYTE_ORDER == __BIG_ENDIAN 833 if (res != expected) {
859 struct phone_codec_data queried_codec;
862 tmp =
ast_channel_alloc(1, state, i->
cid_num, i->
cid_name,
"", i->
ext, i->
context, assignedids, requestor, 0,
"Phone/%s", i->
dev + 5);
869 ioctl(i->
fd, PHONE_QUERY_CODEC, &queried_codec) == 0) {
870 if (queried_codec.type == LINEAR16) {
895 ast_channel_language_set(tmp, i->
language);
929 res = read(i->
fd, buf,
sizeof(buf));
939 char digit[2] = {0 , 0};
940 union telephony_exception phonee;
945 phonee.bytes = ioctl(i->
fd, PHONE_EXCEPTION);
946 if (phonee.bits.dtmf_ready) {
947 digit[0] = ioctl(i->
fd, PHONE_GET_DTMF_ASCII);
949 ioctl(i->
fd, PHONE_PLAY_STOP);
950 ioctl(i->
fd, PHONE_REC_STOP);
951 ioctl(i->
fd, PHONE_CPT_STOP);
954 strncat(i->
ext, digit,
sizeof(i->
ext) - strlen(i->
ext) - 1);
956 !(phonee.bytes = ioctl(i->
fd, PHONE_EXCEPTION)) ||
957 !phonee.bits.dtmf_ready) &&
972 ioctl(i->
fd, PHONE_BUSY);
981 if (phonee.bits.hookstate) {
982 offhook = ioctl(i->
fd, PHONE_HOOKSTATE);
992 ioctl(i->
fd, PHONE_PLAY_STOP);
993 ioctl(i->
fd, PHONE_PLAY_CODEC, ULAW);
994 ioctl(i->
fd, PHONE_PLAY_START);
1003 ioctl(i->
fd, PHONE_DIALTONE);
1008 memset(i->
ext, 0,
sizeof(i->
ext));
1011 ioctl(i->
fd, PHONE_CPT_STOP);
1014 ioctl(i->
fd, PHONE_PLAY_STOP);
1015 ioctl(i->
fd, PHONE_REC_STOP);
1021 if (phonee.bits.pstn_ring) {
1025 if (phonee.bits.caller_id)
1033 struct pollfd *fds =
NULL;
1034 int nfds = 0, inuse_fds = 0, res;
1038 struct timeval to = { 0, 0 };
1058 if (inuse_fds == nfds) {
1067 fds[inuse_fds].fd = i->
fd;
1068 fds[inuse_fds].events = POLLIN | POLLERR;
1069 fds[inuse_fds].revents = 0;
1077 if (write(i->
fd,
DialTone + tonepos, 240) != 240) {
1100 res =
ast_poll(fds, inuse_fds, -1);
1124 for (j = 0; j < inuse_fds; j++) {
1125 if (fds[j].
fd == i->
fd) {
1131 if (j == inuse_fds) {
1135 if (fds[j].revents & POLLIN) {
1141 if (fds[j].revents & POLLERR) {
1197 tmp->
fd = open(iface, O_RDWR);
1204 if (ioctl(tmp->
fd, IXJCTL_PORT, PORT_PSTN)) {
1205 ast_debug(1,
"Unable to set port to PSTN\n");
1208 if (ioctl(tmp->
fd, IXJCTL_PORT, PORT_POTS))
1210 ast_debug(1,
"Unable to set port to POTS\n");
1212 ioctl(tmp->
fd, PHONE_PLAY_STOP);
1213 ioctl(tmp->
fd, PHONE_REC_STOP);
1214 ioctl(tmp->
fd, PHONE_RING_STOP);
1215 ioctl(tmp->
fd, PHONE_CPT_STOP);
1216 if (ioctl(tmp->
fd, PHONE_PSTN_SET_STATE, PSTN_ON_HOOK))
1217 ast_debug(1,
"ioctl(PHONE_PSTN_SET_STATE) failed on %s (%s)\n",iface, strerror(
errno));
1233 memset(tmp->
ext, 0,
sizeof(tmp->
ext));
1244 ioctl(tmp->
fd, PHONE_PLAY_VOLUME, tmp->
txgain);
1246 ioctl(tmp->
fd, PHONE_REC_VOLUME, tmp->
rxgain);
1265 size_t length = strlen(p->
dev + 5);
1266 if (strncmp(name, p->
dev + 5, length) == 0 &&
1267 !isalnum(name[length])) {
1296 if (sscanf(value,
"%30f", &gain) != 1)
1299 value, gain_type,
config);
1307 if (value[strlen(value) - 1] ==
'%')
1308 return (
int)(gain / (float)100);
1422 if (!strcasecmp(v->
name,
"device")) {
1423 tmp =
mkif(v->
value, mode, txgain, rxgain);
1435 }
else if (!strcasecmp(v->
name,
"silencesupression")) {
1437 }
else if (!strcasecmp(v->
name,
"language")) {
1439 }
else if (!strcasecmp(v->
name,
"callerid")) {
1441 }
else if (!strcasecmp(v->
name,
"mode")) {
1442 if (!strncasecmp(v->
value,
"di", 2))
1444 else if (!strncasecmp(v->
value,
"sig", 3))
1446 else if (!strncasecmp(v->
value,
"im", 2))
1448 else if (!strncasecmp(v->
value,
"fxs", 3)) {
1452 else if (!strncasecmp(v->
value,
"fx", 2))
1456 }
else if (!strcasecmp(v->
name,
"context")) {
1458 }
else if (!strcasecmp(v->
name,
"format")) {
1459 if (!strcasecmp(v->
value,
"g729")) {
1462 }
else if (!strcasecmp(v->
value,
"g723.1")) {
1465 }
else if (!strcasecmp(v->
value,
"slinear")) {
1472 }
else if (!strcasecmp(v->
value,
"ulaw")) {
1477 }
else if (!strcasecmp(v->
name,
"echocancel")) {
1478 if (!strcasecmp(v->
value,
"off")) {
1480 }
else if (!strcasecmp(v->
value,
"low")) {
1482 }
else if (!strcasecmp(v->
value,
"medium")) {
1484 }
else if (!strcasecmp(v->
value,
"high")) {
1488 }
else if (!strcasecmp(v->
name,
"txgain")) {
1490 }
else if (!strcasecmp(v->
name,
"rxgain")) {
struct ast_party_caller * ast_channel_caller(struct ast_channel *chan)
struct ast_variable * next
static int parse_gain_value(const char *gain_type, const char *value)
#define ast_channel_lock(chan)
Main Channel structure associated with a channel.
static void phone_mini_packet(struct phone_pvt *i)
char * str
Subscriber phone number (Malloced)
struct ast_format * lastformat
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
static struct ast_frame * phone_read(struct ast_channel *ast)
#define ast_realloc(p, len)
A wrapper for realloc()
static const char config[]
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
static int phone_digit_begin(struct ast_channel *ast, char digit)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
static pthread_t monitor_thread
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static void * do_monitor(void *data)
void * ast_channel_tech_pvt(const struct ast_channel *chan)
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
static int phone_setup(struct ast_channel *ast)
static int phone_write_buf(struct phone_pvt *p, const char *buf, int len, int frlen, int swap)
static ast_mutex_t iflock
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
void ast_channel_set_rawwriteformat(struct ast_channel *chan, struct ast_format *format)
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
#define CONFIG_STATUS_FILEINVALID
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Structure for variables, used for configurations and for channel variables.
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
static struct ast_format_cap * prefcap
static int load_module(void)
void ast_swapcopy_samples(void *dst, const void *src, int samples)
Structure to pass both assignedid values to channel drivers.
ast_channel_state
ast_channel states
static int restart_monitor(void)
static unsigned char DialTone[]
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
static char language[MAX_LANGUAGE]
#define ast_mutex_lock(a)
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
#define ast_str_alloca(init_len)
void ast_verbose(const char *fmt,...)
#define ast_strdup(str)
A wrapper for strdup()
static const char tdesc[]
static struct ast_channel_tech phone_tech
static ast_mutex_t monlock
static struct ast_channel_tech * cur_tech
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define ast_verb(level,...)
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
struct ast_frame_subclass subclass
#define ast_module_unref(mod)
Release a reference to the module.
#define ast_strlen_zero(foo)
#define ast_pthread_create_background(a, b, c, d)
void ast_channel_tech_set(struct ast_channel *chan, const struct ast_channel_tech *value)
Configuration File Parser.
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
#define ast_debug(level,...)
Log a DEBUG message.
void ast_channel_set_rawreadformat(struct ast_channel *chan, struct ast_format *format)
struct ast_channel * owner
#define ast_config_load(filename, flags)
Load a config file.
struct ast_party_id ani
Automatic Number Identification (ANI)
General Asterisk PBX channel definitions.
void ast_channel_rings_set(struct ast_channel *chan, int value)
static struct ast_channel_tech phone_tech_fxs
#define AST_FRIENDLY_OFFSET
Offset into a frame's data buffer.
void ast_channel_nativeformats_set(struct ast_channel *chan, struct ast_format_cap *value)
struct ast_party_connected_line * ast_channel_connected(struct ast_channel *chan)
static struct ast_frame * phone_exception(struct ast_channel *ast)
#define AST_PTHREADT_NULL
#define ast_poll(a, b, c)
#define AST_MAX_EXTENSION
#define ao2_ref(o, delta)
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
void ast_config_destroy(struct ast_config *config)
Destroys a config.
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
static int __unload_module(void)
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
char language[MAX_LANGUAGE]
static int phone_answer(struct ast_channel *ast)
struct ast_format * ast_channel_rawreadformat(struct ast_channel *chan)
char ext[AST_MAX_EXTENSION]
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
char context[AST_MAX_EXTENSION]
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
struct ast_format * lastinput
static unsigned int monitor
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Linux Telephony API Support")
char cid_num[AST_MAX_EXTENSION]
static int phone_call(struct ast_channel *ast, const char *dest, int timeout)
struct ast_format_cap * capabilities
#define ast_channel_unlock(chan)
#define ast_calloc(num, len)
A wrapper for calloc()
#define IXJ_PHONE_RING_START(x)
static struct ast_channel * phone_new(struct phone_pvt *i, int state, char *cntx, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
Module has failed to load, may be in an inconsistent state.
static struct phone_pvt * mkif(const char *iface, int mode, int txgain, int rxgain)
#define DEFAULT_CALLER_ID
Structure used to handle boolean flags.
#define ast_clear_flag(p, flag)
void ast_channel_set_fd(struct ast_channel *chan, int which, int fd)
#define CHECK_BLOCKING(c)
Set the blocking indication on the channel.
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
static int phone_write(struct ast_channel *ast, struct ast_frame *frame)
static struct phone_pvt * iflist
int ast_channel_fd(const struct ast_channel *chan, int which)
static int unload_module(void)
#define ao2_replace(dst, src)
#define ast_frame_byteswap_le(fr)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
char obuf[PHONE_MAX_BUF *2]
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct timeval ast_tv(ast_time_t sec, ast_suseconds_t usec)
Returns a timeval from sec, usec.
const char * ast_channel_name(const struct ast_channel *chan)
char offset[AST_FRIENDLY_OFFSET]
static char context[AST_MAX_EXTENSION]
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
#define AST_PTHREADT_STOP
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
static int phone_send_text(struct ast_channel *ast, const char *text)
union ast_frame::@263 data
static int silencesupression
enum ast_frame_type frametype
static struct ast_channel * phone_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
static int phone_indicate(struct ast_channel *chan, int condition, const void *data, size_t datalen)
char cid_name[AST_MAX_EXTENSION]
struct ast_flags * ast_channel_flags(struct ast_channel *chan)
struct ast_format * format
static int phone_fixup(struct ast_channel *old, struct ast_channel *new)
#define ASTERISK_GPL_KEY
The text the key() function should return.
static int phone_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Asterisk module definitions.
static int phone_hangup(struct ast_channel *ast)
void ast_channel_tech_pvt_set(struct ast_channel *chan, void *value)
unsigned char valid
TRUE if the number information is valid/present.
#define AST_MUTEX_DEFINE_STATIC(mutex)
static void phone_check_exception(struct phone_pvt *i)
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
Same as poll(2), except the time is specified in microseconds and the tv argument is modified to indi...
#define ast_mutex_unlock(a)
struct ast_party_number number
Subscriber phone number.
#define ast_module_ref(mod)
Hold a reference to the module.