Merge "stasic.c: Fix printf format type mismatches with arguments."
[asterisk/asterisk.git] / channels / chan_oss.c
index 3a52ac9..7dde84f 100644 (file)
 
 /*** MODULEINFO
        <depend>oss</depend>
 
 /*** MODULEINFO
        <depend>oss</depend>
-       <support_level>extended</support_level>
+       <support_level>deprecated</support_level>
  ***/
 
 #include "asterisk.h"
 
  ***/
 
 #include "asterisk.h"
 
-ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
-
 #include <ctype.h>             /* isalnum() used here */
 #include <math.h>
 #include <ctype.h>             /* isalnum() used here */
 #include <math.h>
-#include <sys/ioctl.h>         
+#include <sys/ioctl.h>
 
 #ifdef __linux
 #include <linux/soundcard.h>
 
 #ifdef __linux
 #include <linux/soundcard.h>
-#elif defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__GLIBC__)
+#elif defined(__FreeBSD__) || defined(__DragonFly__) || defined(__CYGWIN__) || defined(__GLIBC__) || defined(__sun)
 #include <sys/soundcard.h>
 #else
 #include <soundcard.h>
 #include <sys/soundcard.h>
 #else
 #include <soundcard.h>
@@ -69,6 +67,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 #include "asterisk/musiconhold.h"
 #include "asterisk/app.h"
 #include "asterisk/bridge.h"
 #include "asterisk/musiconhold.h"
 #include "asterisk/app.h"
 #include "asterisk/bridge.h"
+#include "asterisk/format_cache.h"
 
 #include "console_video.h"
 
 
 #include "console_video.h"
 
@@ -256,7 +255,12 @@ struct chan_oss_pvt {
        char *name;
        int total_blocks;                       /*!< total blocks in the output device */
        int sounddev;
        char *name;
        int total_blocks;                       /*!< total blocks in the output device */
        int sounddev;
-       enum { M_UNSET, M_FULL, M_READ, M_WRITE } duplex;
+       enum {
+               CHAN_OSS_DUPLEX_UNSET,
+               CHAN_OSS_DUPLEX_FULL,
+               CHAN_OSS_DUPLEX_READ,
+               CHAN_OSS_DUPLEX_WRITE
+       } duplex;
        int autoanswer;             /*!< Boolean: whether to answer the immediately upon calling */
        int autohangup;             /*!< Boolean: whether to hangup the call when the remote end hangs up */
        int hookstate;              /*!< Boolean: 1 if offhook; 0 if onhook */
        int autoanswer;             /*!< Boolean: whether to answer the immediately upon calling */
        int autohangup;             /*!< Boolean: whether to hangup the call when the remote end hangs up */
        int hookstate;              /*!< Boolean: 1 if offhook; 0 if onhook */
@@ -319,7 +323,7 @@ struct video_desc *get_video_desc(struct ast_channel *c)
 }
 static struct chan_oss_pvt oss_default = {
        .sounddev = -1,
 }
 static struct chan_oss_pvt oss_default = {
        .sounddev = -1,
-       .duplex = M_UNSET,                      /* XXX check this */
+       .duplex = CHAN_OSS_DUPLEX_UNSET, /* XXX check this */
        .autoanswer = 1,
        .autohangup = 1,
        .queuesize = QUEUE_SIZE,
        .autoanswer = 1,
        .autohangup = 1,
        .queuesize = QUEUE_SIZE,
@@ -334,7 +338,7 @@ static struct chan_oss_pvt oss_default = {
 
 static int setformat(struct chan_oss_pvt *o, int mode);
 
 
 static int setformat(struct chan_oss_pvt *o, int mode);
 
-static struct ast_channel *oss_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
+static struct ast_channel *oss_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 oss_digit_begin(struct ast_channel *c, char digit);
 static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration);
                                                                           const char *data, int *cause);
 static int oss_digit_begin(struct ast_channel *c, char digit);
 static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration);
@@ -481,7 +485,7 @@ static int setformat(struct chan_oss_pvt *o, int mode)
        if (o->sounddev >= 0) {
                ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
                close(o->sounddev);
        if (o->sounddev >= 0) {
                ioctl(o->sounddev, SNDCTL_DSP_RESET, 0);
                close(o->sounddev);
-               o->duplex = M_UNSET;
+               o->duplex = CHAN_OSS_DUPLEX_UNSET;
                o->sounddev = -1;
        }
        if (mode == O_CLOSE)            /* we are done */
                o->sounddev = -1;
        }
        if (mode == O_CLOSE)            /* we are done */
@@ -514,16 +518,16 @@ static int setformat(struct chan_oss_pvt *o, int mode)
                res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
                if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
                        ast_verb(2, "Console is full duplex\n");
                res = ioctl(fd, SNDCTL_DSP_GETCAPS, &fmt);
                if (res == 0 && (fmt & DSP_CAP_DUPLEX)) {
                        ast_verb(2, "Console is full duplex\n");
-                       o->duplex = M_FULL;
+                       o->duplex = CHAN_OSS_DUPLEX_FULL;
                };
                break;
 
        case O_WRONLY:
                };
                break;
 
        case O_WRONLY:
-               o->duplex = M_WRITE;
+               o->duplex = CHAN_OSS_DUPLEX_WRITE;
                break;
 
        case O_RDONLY:
                break;
 
        case O_RDONLY:
-               o->duplex = M_READ;
+               o->duplex = CHAN_OSS_DUPLEX_READ;
                break;
        }
 
                break;
        }
 
@@ -581,7 +585,7 @@ static int oss_digit_begin(struct ast_channel *c, char digit)
 static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
        /* no better use for received digits than print them */
 static int oss_digit_end(struct ast_channel *c, char digit, unsigned int duration)
 {
        /* no better use for received digits than print them */
-       ast_verbose(" << Console Received digit %c of duration %u ms >> \n", 
+       ast_verbose(" << Console Received digit %c of duration %u ms >> \n",
                digit, duration);
        return 0;
 }
                digit, duration);
        return 0;
 }
@@ -726,7 +730,7 @@ static struct ast_frame *oss_read(struct ast_channel *c)
                return f;
        /* ok we can build and deliver the frame to the caller */
        f->frametype = AST_FRAME_VOICE;
                return f;
        /* ok we can build and deliver the frame to the caller */
        f->frametype = AST_FRAME_VOICE;
-       ast_format_set(&f->subclass.format, AST_FORMAT_SLINEAR, 0);
+       f->subclass.format = ast_format_slin;
        f->samples = FRAME_SIZE;
        f->datalen = FRAME_SIZE * 2;
        f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET;
        f->samples = FRAME_SIZE;
        f->datalen = FRAME_SIZE * 2;
        f->data.ptr = o->oss_read_buf + AST_FRIENDLY_OFFSET;
@@ -792,11 +796,11 @@ static int oss_indicate(struct ast_channel *c, int cond, const void *data, size_
 /*!
  * \brief allocate a new channel.
  */
 /*!
  * \brief allocate a new channel.
  */
-static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, int state, const char *linkedid)
+static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
 {
        struct ast_channel *c;
 
 {
        struct ast_channel *c;
 
-       c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, linkedid, 0, "Console/%s", o->device + 5);
+       c = ast_channel_alloc(1, state, o->cid_num, o->cid_name, "", ext, ctx, assignedids, requestor, 0, "Console/%s", o->device + 5);
        if (c == NULL)
                return NULL;
        ast_channel_tech_set(c, &oss_tech);
        if (c == NULL)
                return NULL;
        ast_channel_tech_set(c, &oss_tech);
@@ -804,9 +808,9 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
                setformat(o, O_RDWR);
        ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
 
                setformat(o, O_RDWR);
        ast_channel_set_fd(c, 0, o->sounddev); /* -1 if device closed, override later */
 
-       ast_format_set(ast_channel_readformat(c), AST_FORMAT_SLINEAR, 0);
-       ast_format_set(ast_channel_writeformat(c), AST_FORMAT_SLINEAR, 0);
-       ast_format_cap_add(ast_channel_nativeformats(c), ast_channel_readformat(c));
+       ast_channel_set_readformat(c, ast_format_slin);
+       ast_channel_set_writeformat(c, ast_format_slin);
+       ast_channel_nativeformats_set(c, oss_tech.capabilities);
 
        /* if the console makes the call, add video to the offer */
        /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER
 
        /* if the console makes the call, add video to the offer */
        /* if (state == AST_STATE_RINGING) TODO XXX CONSOLE VIDEO IS DISABLED UNTIL IT GETS A MAINTAINER
@@ -842,7 +846,7 @@ static struct ast_channel *oss_new(struct chan_oss_pvt *o, char *ext, char *ctx,
        return c;
 }
 
        return c;
 }
 
-static struct ast_channel *oss_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
+static struct ast_channel *oss_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)
 {
        struct ast_channel *c;
        struct chan_oss_pvt *o;
 {
        struct ast_channel *c;
        struct chan_oss_pvt *o;
@@ -851,8 +855,6 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
                AST_APP_ARG(flags);
        );
        char *parse = ast_strdupa(data);
                AST_APP_ARG(flags);
        );
        char *parse = ast_strdupa(data);
-       char buf[256];
-       struct ast_format tmpfmt;
 
        AST_NONSTANDARD_APP_ARGS(args, parse, '/');
        o = find_desc(args.name);
 
        AST_NONSTANDARD_APP_ARGS(args, parse, '/');
        o = find_desc(args.name);
@@ -863,8 +865,9 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
                /* XXX we could default to 'dsp' perhaps ? */
                return NULL;
        }
                /* XXX we could default to 'dsp' perhaps ? */
                return NULL;
        }
-       if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)))) {
-               ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_getformatname_multiple(buf, sizeof(buf), cap));
+       if (ast_format_cap_iscompatible_format(cap, ast_format_slin) == AST_FORMAT_CMP_NOT_EQUAL) {
+               struct ast_str *codec_buf = ast_str_alloca(AST_FORMAT_CAP_NAMES_LEN);
+               ast_log(LOG_NOTICE, "Format %s unsupported\n", ast_format_cap_get_names(cap, &codec_buf));
                return NULL;
        }
        if (o->owner) {
                return NULL;
        }
        if (o->owner) {
@@ -872,7 +875,7 @@ static struct ast_channel *oss_request(const char *type, struct ast_format_cap *
                *cause = AST_CAUSE_BUSY;
                return NULL;
        }
                *cause = AST_CAUSE_BUSY;
                return NULL;
        }
-       c = oss_new(o, NULL, NULL, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
+       c = oss_new(o, NULL, NULL, AST_STATE_DOWN, assignedids, requestor);
        if (c == NULL) {
                ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
                return NULL;
        if (c == NULL) {
                ast_log(LOG_WARNING, "Unable to create new OSS channel\n");
                return NULL;
@@ -892,7 +895,7 @@ static char *console_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *
        switch (cmd) {
        case CLI_INIT:
                e->command = CONSOLE_VIDEO_CMDS;
        switch (cmd) {
        case CLI_INIT:
                e->command = CONSOLE_VIDEO_CMDS;
-               e->usage = 
+               e->usage =
                        "Usage: " CONSOLE_VIDEO_CMDS "...\n"
                        "       Generic handler for console commands.\n";
                return NULL;
                        "Usage: " CONSOLE_VIDEO_CMDS "...\n"
                        "       Generic handler for console commands.\n";
                return NULL;
@@ -1131,7 +1134,7 @@ static char *console_dial(struct ast_cli_entry *e, int cmd, struct ast_cli_args
                myc = o->ctx;
        if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
                o->hookstate = 1;
                myc = o->ctx;
        if (ast_exists_extension(NULL, myc, mye, 1, NULL)) {
                o->hookstate = 1;
-               oss_new(o, mye, myc, AST_STATE_RINGING, NULL);
+               oss_new(o, mye, myc, AST_STATE_RINGING, NULL, NULL);
        } else
                ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
        if (s)
        } else
                ast_cli(a->fd, "No such extension '%s' in context '%s'\n", mye, myc);
        if (s)
@@ -1144,7 +1147,7 @@ static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args
        struct chan_oss_pvt *o = find_desc(oss_active);
        const char *s;
        int toggle = 0;
        struct chan_oss_pvt *o = find_desc(oss_active);
        const char *s;
        int toggle = 0;
-       
+
        if (cmd == CLI_INIT) {
                e->command = "console {mute|unmute} [toggle]";
                e->usage =
        if (cmd == CLI_INIT) {
                e->command = "console {mute|unmute} [toggle]";
                e->usage =
@@ -1175,7 +1178,6 @@ static char *console_mute(struct ast_cli_entry *e, int cmd, struct ast_cli_args
 static char *console_transfer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct chan_oss_pvt *o = find_desc(oss_active);
 static char *console_transfer(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
        struct chan_oss_pvt *o = find_desc(oss_active);
-       RAII_VAR(struct ast_channel *, b, NULL, ast_channel_cleanup);
        char *tmp, *ext, *ctx;
 
        switch (cmd) {
        char *tmp, *ext, *ctx;
 
        switch (cmd) {
@@ -1295,7 +1297,7 @@ static struct ast_cli_entry cli_oss[] = {
        AST_CLI_DEFINE(console_flash, "Flash a call on the console"),
        AST_CLI_DEFINE(console_dial, "Dial an extension on the console"),
        AST_CLI_DEFINE(console_mute, "Disable/Enable mic input"),
        AST_CLI_DEFINE(console_flash, "Flash a call on the console"),
        AST_CLI_DEFINE(console_dial, "Dial an extension on the console"),
        AST_CLI_DEFINE(console_mute, "Disable/Enable mic input"),
-       AST_CLI_DEFINE(console_transfer, "Transfer a call to a different extension"),   
+       AST_CLI_DEFINE(console_transfer, "Transfer a call to a different extension"),
        AST_CLI_DEFINE(console_cmd, "Generic console command"),
        AST_CLI_DEFINE(console_sendtext, "Send text to the remote device"),
        AST_CLI_DEFINE(console_autoanswer, "Sets/displays autoanswer"),
        AST_CLI_DEFINE(console_cmd, "Generic console command"),
        AST_CLI_DEFINE(console_sendtext, "Send text to the remote device"),
        AST_CLI_DEFINE(console_autoanswer, "Sets/displays autoanswer"),
@@ -1419,7 +1421,7 @@ openit:
                ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
                goto error;
        }
                ast_verb(1, "Turn off OSS support by adding " "'noload=chan_oss.so' in /etc/asterisk/modules.conf\n");
                goto error;
        }
-       if (o->duplex != M_FULL)
+       if (o->duplex != CHAN_OSS_DUPLEX_FULL)
                ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n");
 #endif /* TRYOPEN */
 
                ast_log(LOG_WARNING, "XXX I don't work right with non " "full-duplex sound cards XXX\n");
 #endif /* TRYOPEN */
 
@@ -1438,14 +1440,39 @@ error:
 #endif
 }
 
 #endif
 }
 
+static int unload_module(void)
+{
+       struct chan_oss_pvt *o, *next;
+
+       ast_channel_unregister(&oss_tech);
+       ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss));
+
+       o = oss_default.next;
+       while (o) {
+               close(o->sounddev);
+               if (o->owner)
+                       ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
+               if (o->owner)
+                       return -1;
+               next = o->next;
+               ast_free(o->name);
+               ast_free(o);
+               o = next;
+       }
+       ao2_cleanup(oss_tech.capabilities);
+       oss_tech.capabilities = NULL;
+
+       return 0;
+}
+
 /*!
  * \brief Load the module
  *
  * Module loading including tests for configuration or dependencies.
  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
 /*!
  * \brief Load the module
  *
  * Module loading including tests for configuration or dependencies.
  * This function can return AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_DECLINE,
  * or AST_MODULE_LOAD_SUCCESS. If a dependency or environment variable fails
- * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the 
- * configuration file or other non-critical problem return 
+ * tests return AST_MODULE_LOAD_FAILURE. If the module can not load the
+ * configuration file or other non-critical problem return
  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
  */
 static int load_module(void)
  * AST_MODULE_LOAD_DECLINE. On success return AST_MODULE_LOAD_SUCCESS.
  */
 static int load_module(void)
@@ -1453,7 +1480,6 @@ static int load_module(void)
        struct ast_config *cfg = NULL;
        char *ctg = NULL;
        struct ast_flags config_flags = { 0 };
        struct ast_config *cfg = NULL;
        char *ctg = NULL;
        struct ast_flags config_flags = { 0 };
-       struct ast_format tmpfmt;
 
        /* Copy the default jb config over global_jbconf */
        memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
 
        /* Copy the default jb config over global_jbconf */
        memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
@@ -1476,14 +1502,14 @@ static int load_module(void)
        if (find_desc(oss_active) == NULL) {
                ast_log(LOG_NOTICE, "Device %s not found\n", oss_active);
                /* XXX we could default to 'dsp' perhaps ? */
        if (find_desc(oss_active) == NULL) {
                ast_log(LOG_NOTICE, "Device %s not found\n", oss_active);
                /* XXX we could default to 'dsp' perhaps ? */
-               /* XXX should cleanup allocated memory etc. */
-               return AST_MODULE_LOAD_FAILURE;
+               unload_module();
+               return AST_MODULE_LOAD_DECLINE;
        }
 
        if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) {
        }
 
        if (!(oss_tech.capabilities = ast_format_cap_alloc(0))) {
-               return AST_MODULE_LOAD_FAILURE;
+               return AST_MODULE_LOAD_DECLINE;
        }
        }
-       ast_format_cap_add(oss_tech.capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
+       ast_format_cap_append(oss_tech.capabilities, ast_format_slin, 0);
 
        /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER
         * add console_video_formats to oss_tech.capabilities once this occurs. */
 
        /* TODO XXX CONSOLE VIDEO IS DISABLE UNTIL IT HAS A MAINTAINER
         * add console_video_formats to oss_tech.capabilities once this occurs. */
@@ -1498,28 +1524,4 @@ static int load_module(void)
        return AST_MODULE_LOAD_SUCCESS;
 }
 
        return AST_MODULE_LOAD_SUCCESS;
 }
 
-
-static int unload_module(void)
-{
-       struct chan_oss_pvt *o, *next;
-
-       ast_channel_unregister(&oss_tech);
-       ast_cli_unregister_multiple(cli_oss, ARRAY_LEN(cli_oss));
-
-       o = oss_default.next;
-       while (o) {
-               close(o->sounddev);
-               if (o->owner)
-                       ast_softhangup(o->owner, AST_SOFTHANGUP_APPUNLOAD);
-               if (o->owner)
-                       return -1;
-               next = o->next;
-               ast_free(o->name);
-               ast_free(o);
-               o = next;
-       }
-       oss_tech.capabilities = ast_format_cap_destroy(oss_tech.capabilities);
-       return 0;
-}
-
-AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "OSS Console Channel Driver");
+AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "OSS Console Channel Driver");