diff -wur slmodem-2.9.11-20080817/drivers/modules.order slmodem-2.9.11-20080817-matias/drivers/modules.order
--- slmodem-2.9.11-20080817/drivers/modules.order	2008-08-17 23:37:28.000000000 -0300
+++ slmodem-2.9.11-20080817-matias/drivers/modules.order	2008-12-23 23:00:37.429217318 -0200
@@ -1 +1 @@
-kernel//usr/src/modules/slmodem-2.9.11-20080811/drivers/slamr.ko
+kernel//home/paulo/projetos/modem/slmodem-2.9.11-20080817-matias/drivers/slamr.ko
diff -wur slmodem-2.9.11-20080817/modem/Makefile slmodem-2.9.11-20080817-matias/modem/Makefile
--- slmodem-2.9.11-20080817/modem/Makefile	2008-04-18 00:06:17.000000000 -0300
+++ slmodem-2.9.11-20080817-matias/modem/Makefile	2008-12-26 16:37:09.092196112 -0200
@@ -19,6 +19,7 @@
 CC:= gcc
 else
 # SUPPORT_ALSA:=1
+# SUPPORT_OSS:=1
 CC:= gcc -m32
 endif
 
@@ -49,6 +50,11 @@
 endif
 endif
 
+ifdef SUPPORT_OSS
+include /etc/oss.conf
+CFLAGS+= -DSUPPORT_OSS=1 -I$(OSSLIBDIR)/include/sys
+endif
+
 slmodemd:
 	$(CC) -o slmodemd modem_main.o $(all-objs) $(LFLAGS)
 
diff -wur slmodem-2.9.11-20080817/modem/modem_cmdline.c slmodem-2.9.11-20080817-matias/modem/modem_cmdline.c
--- slmodem-2.9.11-20080817/modem/modem_cmdline.c	2008-03-29 09:04:16.000000000 -0300
+++ slmodem-2.9.11-20080817-matias/modem/modem_cmdline.c	2008-12-26 14:50:06.326171478 -0200
@@ -67,6 +67,7 @@
 
 /* config parameters */
 const char *modem_dev_name = NULL;
+const char *modem_dev_name_out = NULL;
 const char *modem_default_dev_name = "/dev/slamr0";
 const char *modem_alsa_dev_name = "modem:1";
 unsigned int need_realtime = 1;
@@ -74,6 +75,7 @@
 unsigned int ring_detector = 0;
 #endif
 unsigned int use_alsa = 0;
+unsigned int use_oss = 0;
 unsigned int use_short_buffer = 0;
 const char *modem_group = "uucp";
 mode_t modem_perm  = 0660;
@@ -86,6 +88,7 @@
 	OPT_COUNTRY,
 	OPT_COUNTRYLIST,
 	OPT_ALSA,
+	OPT_OSS,
 	OPT_GROUP,
 	OPT_PERM,
 #ifdef MODEM_CONFIG_RING_DETECTOR
@@ -113,6 +116,7 @@
 	{'c',"country","default modem country name",MANDATORY,STRING,"USA"},
 	{ 0 ,"countrylist","show list of supported countries"},
 	{'a',"alsa","ALSA mode (see README for howto)"},
+	{'o',"oss","OSS mode (see README.OSS for howto)"},
 	{'g',"group","Modem TTY group",MANDATORY,STRING,"uucp"},
 	{'p',"perm","Modem TTY permission",MANDATORY,INTEGER,"0660"},
 #ifdef MODEM_CONFIG_RING_DETECTOR
@@ -130,7 +134,7 @@
 static void usage(const char *prog_name)
 {
 	struct opt *opt;
-	PR_INFO("Usage: %s [option...] <device>\n"
+	PR_INFO("Usage: %s [option...] < <device> | <in-device> <out-device> >\n"
 		"Where 'device' is name of modem device (default `%s')\n"
 		"  and 'option' may be:\n", prog_name, modem_default_dev_name);
 	for (opt = opt_list ; opt->name ; opt++ ) {
@@ -154,6 +158,7 @@
 {
 	const char *prog_name;
 	const char *dev_name = NULL;
+	const char *dev_name_out = NULL;
 	struct opt *opt;
 	char *p, *arg;
 	int found, i;
@@ -163,8 +168,13 @@
 	for( i = 1 ; i < argc ; i++ ) {
 		p = argv[i];
 		if(*p != '-') {
-			if(dev_name)
+			if(dev_name) {
+				if(dev_name_out) {
 				usage(prog_name);
+				}
+				dev_name_out = p;
+				continue;
+			}
 			dev_name = p;
 			continue;
 		}
@@ -215,6 +225,8 @@
 
 	if(dev_name)
 		modem_dev_name = dev_name;
+	if(dev_name_out)
+		modem_dev_name_out = dev_name_out;
 }
 
 
@@ -252,6 +264,17 @@
 #endif
 		use_alsa = 1;
 	}
+	if(opt_list[OPT_OSS].found) {
+#ifndef SUPPORT_OSS
+		PR_INFO("OSS support is not compiled in (see README.OSS for howto).\n");
+		exit(1);
+#endif
+		if(use_alsa) {
+			PR_INFO("Using OSS.\n");
+			use_alsa = 0;
+		}
+		use_oss = 1;
+	}
 	if(opt_list[OPT_GROUP].found)
 		modem_group = opt_list[OPT_GROUP].arg_val;
 	if(opt_list[OPT_PERM].found) {
@@ -283,5 +306,9 @@
 	if(!modem_dev_name) {
 		modem_dev_name = use_alsa ? modem_alsa_dev_name : modem_default_dev_name;
 	}
+	if(use_oss && ((!modem_dev_name) || (!modem_dev_name_out))) {
+		PR_INFO("OSS driver requires you to provide an input device and an output device.\n");
+		exit(1);
+	}
 }
 
diff -wur slmodem-2.9.11-20080817/modem/modem_main.c slmodem-2.9.11-20080817-matias/modem/modem_main.c
--- slmodem-2.9.11-20080817/modem/modem_main.c	2008-08-03 22:40:13.000000000 -0300
+++ slmodem-2.9.11-20080817-matias/modem/modem_main.c	2008-12-26 16:41:25.285873465 -0200
@@ -67,6 +67,10 @@
 #define SHORT_BUFFER_PERIODS	4
 #endif
 
+#ifdef SUPPORT_OSS
+#include <soundcard.h>
+#endif
+
 #include <modem.h>
 #include <modem_debug.h>
 
@@ -92,6 +96,7 @@
 
 /* global config data */
 extern const char *modem_dev_name;
+extern const char *modem_dev_name_out;
 extern unsigned int ring_detector;
 extern unsigned int need_realtime;
 extern const char *modem_group;
@@ -113,6 +118,9 @@
 	unsigned int buf_periods;
 	unsigned int started;
 #endif
+#ifdef SUPPORT_OSS
+    int fd_out;
+#endif
 	int delay;
 };
 
@@ -542,6 +550,158 @@
 
 
 /*
+ *    OSS 'driver'
+ *
+ */
+
+#ifdef SUPPORT_OSS
+
+extern unsigned use_oss;
+
+static int oss_device_setup(struct device_struct *dev, const char *dev_name)
+{
+    memset(dev,0,sizeof(*dev));
+
+    if((dev->fd = open(modem_dev_name,O_RDWR)) < 0) {
+        ERR("oss setup: cannot open dev `%s': %s\n",modem_dev_name,strerror(errno));
+        return -1;
+    }
+
+    if((dev->fd_out = open(modem_dev_name_out,O_RDWR)) < 0) {
+        ERR("oss setup: cannot open dev `%s': %s\n",modem_dev_name_out,strerror(errno));
+        return -1;
+    }
+
+    dev->num = 0;
+    return 0;
+}
+
+static int oss_device_release(struct device_struct *dev)
+{
+    close(dev->fd);
+    close(dev->fd_out);
+    return 0;
+}
+
+
+static int oss_device_read(struct device_struct *dev, char *buf, int size)
+{
+    /* We are using 16 bit samples. The 'size' argument and the return
+     * value are specified in samples. */
+    int ret = read(dev->fd, buf, size*2);
+    if (ret > 0) ret /= 2;
+    return ret;
+}
+
+static int oss_device_write(struct device_struct *dev, const char *buf, int size)
+{
+    /* We are using 16 bit samples. The 'size' argument and the return
+     * value are specified in samples. */
+    int ret = write(dev->fd_out, buf, size*2);
+    if (ret > 0) ret /= 2;
+    return ret;
+}
+
+static int oss_start (struct modem *m)
+{
+    struct device_struct *dev = m->dev_data;
+    static int dev_ready = 0;
+    int tmp;
+    DBG("oss_start...\n");
+    
+    if(!dev_ready) {
+        /* buffer size */
+        tmp=(m->frag<<16)|4;
+        if ( (ioctl(dev->fd,     SNDCTL_DSP_SETFRAGMENT, &tmp) < 0)
+           ||(ioctl(dev->fd_out, SNDCTL_DSP_SETFRAGMENT, &tmp) < 0) ) {
+            perror("set fragment");
+            return -1;
+        }
+
+        tmp = 1;
+        if ( (ioctl(dev->fd,     SNDCTL_DSP_CHANNELS, &tmp) < 0)
+           ||(ioctl(dev->fd_out, SNDCTL_DSP_CHANNELS, &tmp) < 0) ) {
+            perror("set channels");
+            return -1;
+        }
+
+        tmp=AFMT_S16_LE;
+        if ( (ioctl(dev->fd,     SNDCTL_DSP_SETFMT, &tmp) < 0)
+           ||(ioctl(dev->fd_out, SNDCTL_DSP_SETFMT, &tmp) < 0) ) {
+            perror("set format");
+            return -1;
+        }
+    
+        tmp = m->srate;
+        if ( (ioctl(dev->fd,     SNDCTL_DSP_SPEED, &tmp) < 0)
+           ||(ioctl(dev->fd_out, SNDCTL_DSP_SPEED, &tmp) < 0) ) {
+            perror("set rate");
+            return -1;
+        }
+    }
+
+    tmp = 0;
+    ioctl(dev->fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+    tmp = PCM_ENABLE_INPUT;
+    ioctl(dev->fd, SNDCTL_DSP_SETTRIGGER, &tmp);
+
+    if(!dev_ready) {
+        tmp = 0;
+        ioctl(dev->fd_out, SNDCTL_DSP_SETTRIGGER, &tmp);
+        tmp = PCM_ENABLE_OUTPUT;
+        ioctl(dev->fd_out, SNDCTL_DSP_SETTRIGGER, &tmp);
+    }
+
+    dev_ready = 1;
+
+    return 0;
+}
+
+static int oss_stop (struct modem *m)
+{
+    struct device_struct *dev = m->dev_data;
+    DBG("oss_stop...\n");
+    ioctl(dev->fd,     SNDCTL_DSP_HALT, NULL);
+    ioctl(dev->fd_out, SNDCTL_DSP_HALT, NULL);
+    return 0;
+}
+
+static int oss_ioctl(struct modem *m, unsigned int cmd, unsigned long arg)
+{
+    struct device_struct *dev = m->dev_data;
+    int tmp;
+    switch(cmd) {
+        case MDMCTL_CAPABILITIES:
+            return -EINVAL;
+        case MDMCTL_HOOKSTATE:
+	    tmp = (arg == MODEM_HOOK_OFF);
+	    ioctl(dev->fd, SNDCTL_DSP_MODEM_OFFHOOK, &tmp);
+            return 0; 
+        case MDMCTL_SPEAKERVOL:
+            tmp = 100*arg/3; /* 0 <= arg <= 3 */ 
+            tmp = (tmp << 8) | tmp;
+            return ioctl(dev->fd_out, SNDCTL_DSP_SETPLAYVOL, &tmp);
+        case MDMCTL_CODECTYPE:
+            return CODEC_SILABS;
+        case MDMCTL_IODELAY:
+            return dev->delay;
+    }
+    return 0;
+}
+
+
+struct modem_driver oss_modem_driver = {
+        .name = "oss modem driver",
+        .start = oss_start,
+        .stop = oss_stop,
+        .ioctl = oss_ioctl,
+};
+
+
+#endif
+
+
+/*
  *    'driver' stuff
  *
  */
@@ -810,6 +970,12 @@
 				continue;
 			}
 #endif
+#ifdef SUPPORT_OSS
+            if(use_oss) {
+                DBG("dev exception...\n");
+                continue;
+            }
+#endif
 			ret = ioctl(dev->fd,MDMCTL_GETSTAT,&stat);
 			if(ret < 0) {
 				ERR("dev ioctl: %s\n",strerror(errno));
@@ -1037,6 +1203,15 @@
 		modem_driver = &alsa_modem_driver;
 	}
 #endif
+#ifdef SUPPORT_OSS
+    if(use_oss) {
+        device_setup = oss_device_setup;
+        device_release = oss_device_release;
+        device_read = oss_device_read;
+        device_write = oss_device_write;
+        modem_driver = &oss_modem_driver;
+    }
+#endif
 
 	ret = modem_main(modem_dev_name);
 	return ret;