--- channels/chan_sip.c.orig	2010-08-19 23:03:24.000000000 +0200
+++ channels/chan_sip.c	2010-09-15 21:27:43.000000000 +0200
@@ -865,6 +865,7 @@
 /*! \brief T38 States for a call */
 enum t38state {
         T38_DISABLED = 0,                /*!< Not enabled */
+        T38_LOCAL_DIRECT,                /*!< Offered from local - Direct T38 only call*/
         T38_LOCAL_REINVITE,              /*!< Offered from local - REINVITE */
         T38_PEER_DIRECT,                 /*!< Offered from peer */
         T38_PEER_REINVITE,               /*!< Offered from peer - REINVITE */
@@ -3248,6 +3249,10 @@
 		} else if (!strcasecmp(ast_var_name(current), "SIPTRANSFER_REPLACES")) {
 			/* We're replacing a call. */
 			p->options->replaces = ast_var_value(current);
+		} else if (!strcasecmp(ast_var_name(current), "T38CALL")) { 		
+			p->t38.state = T38_LOCAL_DIRECT; 		
+			if (option_debug) 		
+				ast_log(LOG_DEBUG,"T38State change to %d on channel %s\n", p->t38.state, ast->name);
 		}
 	}
 	
@@ -4042,7 +4047,7 @@
 				Fax will re-transmit.
 			*/
 			if (ast->_state == AST_STATE_UP) {
-				if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && p->t38.state == T38_DISABLED) {
+				if (ast_test_flag(&p->flags[1], SIP_PAGE2_T38SUPPORT) && (p->t38.state == T38_DISABLED || p->t38.state == T38_LOCAL_DIRECT)) {
 					if (!p->pendinginvite) {
 						p->t38.state = T38_LOCAL_REINVITE;
 						transmit_reinvite_with_t38_sdp(p);
@@ -4331,7 +4336,15 @@
 		video = global_capability & AST_FORMAT_VIDEO_MASK;
 	}
 
-	/* Set the native formats for audio  and merge in video */
+	/* On T38 only calls we must set a native format to fool channel.c 
+	   But we must also set the proper channel variable to inform the new channel
+       and so that users can choose not to playback audio on T38 only calls */ 		
+	if (i->t38.jointcapability && !i->jointcapability && !i->capability) {
+		ast_log(LOG_DEBUG, "*** T.38 Fax only call, setting native formats anyway. \n");
+		pbx_builtin_setvar_helper(tmp, "_T38CALL", "1");
+	} 
+
+	/* Set the native formats for audio and merge in video */
 	tmp->nativeformats = ast_codec_choose(&i->prefs, what, 1) | video;
 	if (option_debug > 2) {
 		char buf[SIPBUFSIZE];
@@ -4686,7 +4699,7 @@
 
 	/* If we are NOT bridged to another channel, and we have detected fax tone we issue T38 re-invite to a peer */
 	/* If we are bridged then it is the responsibility of the SIP device to issue T38 re-invite if it detects CNG or fax preamble */
-	if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && (p->t38.state == T38_DISABLED) && !(ast_bridged_channel(ast))) {
+	if (faxdetected && ast_test_flag(&p->t38.t38support, SIP_PAGE2_T38SUPPORT_UDPTL) && (p->t38.state == T38_DISABLED || p->t38.state == T38_LOCAL_DIRECT) && !(ast_bridged_channel(ast))) {
 		if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
 			if (!p->pendinginvite) {
 				if (option_debug > 2)
@@ -5596,7 +5609,7 @@
 			numberofmediastreams++;
 			
 			if (p->owner && p->lastinvite) {
-				if (p->t38.state != T38_LOCAL_REINVITE) {
+				if (p->t38.state != T38_LOCAL_REINVITE && p->t38.state != T38_LOCAL_DIRECT) {
 					p->t38.state = T38_PEER_REINVITE; /* T38 Offered in re-invite from remote party */
 					if (option_debug > 1)
 						ast_log(LOG_DEBUG, "T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>" );
@@ -5733,7 +5746,7 @@
 			return -1;
 		} else {
 			if (option_debug > 2)
-				ast_log(LOG_DEBUG, "Have T.38 but no audio codecs, accepting offer anyway\n");
+				ast_log(LOG_DEBUG, "We have a T38 only call\n");
 		}
 	}
 
@@ -7034,7 +7047,7 @@
 		dest.sin_port = sin.sin_port;
 	}
 
-        snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
+	snprintf(owner, sizeof(owner), "o=root %d %d IN IP4 %s\r\n", p->sessionid, p->sessionversion, ast_inet_ntoa(dest.sin_addr));
 	snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(dest.sin_addr));
 
 	if (ast_test_flag(&p->flags[1], SIP_PAGE2_CALL_ONHOLD) == SIP_PAGE2_CALL_ONHOLD_ONEDIR)
@@ -7202,13 +7215,17 @@
 		}
 
 		if (debug) {
-			ast_log(LOG_DEBUG, "T.38 UDPTL is at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
+			ast_log(LOG_DEBUG, "T38 UDPTL is currently at %s port %d\n", ast_inet_ntoa(p->ourip), ntohs(udptlsin.sin_port));
+			if (p->udptlredirip.sin_addr.s_addr)
+				ast_log(LOG_DEBUG, "T38 UDPTL will be sent to %s port %d\n", ast_inet_ntoa(udptldest.sin_addr), ntohs(udptldest.sin_port));
 			ast_log(LOG_DEBUG, "Our T38 capability (%d), peer T38 capability (%d), joint capability (%d)\n",
 				p->t38.capability,
 				p->t38.peercapability,
 				p->t38.jointcapability);
 		}
 
+		snprintf(connection, sizeof(connection), "c=IN IP4 %s\r\n", ast_inet_ntoa(udptldest.sin_addr));
+
 		ast_build_string(&m_modem_next, &m_modem_left, "m=image %d udptl t38\r\n", ntohs(udptldest.sin_port));
 
 		if ((p->t38.jointcapability & T38FAX_VERSION) == T38FAX_VERSION_0)
@@ -7411,7 +7428,7 @@
 }
 
 /*! \brief Transmit reinvite with T38 SDP 
-       We reinvite so that the T38 processing can take place.
+       We reinvite so that the T38 processing can take place after "T38 switchover" or for "T38 only" calls.
        SIP Signalling stays with * in the path.
 */
 static int transmit_reinvite_with_t38_sdp(struct sip_pvt *p)
@@ -7423,7 +7440,7 @@
 	add_header(&req, "Allow", ALLOWED_METHODS);
 	add_header(&req, "Supported", SUPPORTED_EXTENSIONS);
 	if (sipdebug)
-		add_header(&req, "X-asterisk-info", "SIP re-invite (T38 switchover)");
+		add_header(&req, "X-asterisk-info", "SIP re-invite (T38 call)");
 	memset(p->offered_media, 0, sizeof(p->offered_media));
 	add_sdp(&req, p, 0, 1);
 
@@ -7758,11 +7775,14 @@
 	}
 	if (sdp) {
 		memset(p->offered_media, 0, sizeof(p->offered_media));
-		if (p->udptl && p->t38.state == T38_LOCAL_REINVITE) {
-			ast_udptl_offered_from_local(p->udptl, 1);
+		if (p->udptl) {
 			if (option_debug)
 				ast_log(LOG_DEBUG, "T38 is in state %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
-			add_sdp(&req, p, 0, 1);
+			ast_udptl_offered_from_local(p->udptl, 1);
+			if (p->t38.state == T38_LOCAL_REINVITE || p->t38.state == T38_LOCAL_DIRECT) 
+				add_sdp(&req, p, 0, 1);
+			else
+				add_sdp(&req, p, 1, 1);
 		} else if (p->rtp) 
 			add_sdp(&req, p, 1, 0);
 	}
@@ -12920,7 +12940,11 @@
 			if (option_debug)
 				ast_log(LOG_DEBUG, "Sending pending reinvite on '%s'\n", p->callid);
 			/* Didn't get to reinvite yet, so do it now */
-			transmit_reinvite_with_sdp(p);
+			if (p->t38.state == T38_ENABLED )
+				transmit_reinvite_with_t38_sdp(p);
+			else
+				transmit_reinvite_with_sdp(p);
+
 			ast_clear_flag(&p->flags[0], SIP_NEEDREINVITE);
 		}
 	}
@@ -13105,7 +13129,7 @@
 					ast_log(LOG_DEBUG,"T38 state changed to %d on channel %s\n", p->t38.state, p->owner ? p->owner->name : "<none>");
 			}
 		}
-		if (p->t38.state == T38_LOCAL_REINVITE) {
+		if (p->t38.state == T38_LOCAL_REINVITE || p->t38.state == T38_LOCAL_DIRECT) {
 			/* If there was T38 reinvite and we are supposed to answer with 200 OK than this should set us to T38 negotiated mode */
 			p->t38.state = T38_ENABLED;
 			if (option_debug)
@@ -18984,11 +19008,13 @@
 	p = chan->tech_pvt;
 	if (!p)
 		return -1;
+
 	ast_mutex_lock(&p->lock);
 	if (udptl)
 		ast_udptl_get_peer(udptl, &p->udptlredirip);
 	else
 		memset(&p->udptlredirip, 0, sizeof(p->udptlredirip));
+
 	if (!ast_test_flag(&p->flags[0], SIP_GOTREFER)) {
 		if (!p->pendinginvite) {
 			if (option_debug > 2) {
@@ -19172,6 +19198,15 @@
 	if (!p) 
 		return -1;
 
+	/* If this is a re-invite of an established T38 session, use sip_set_udptl_peer instead */
+	if (p->t38.state == T38_ENABLED) {
+		ast_log(LOG_WARNING,"Call %s cannot re-invite because its T38 only (not yet supported).\n", p->callid);
+		/* Re-Invite might be made possible by calling "return sip_set_udptl_peer(chan, p->udptl);" right here
+		   however the "p-udptl" hold the wrong information so it would cause the peer to invite itself :-(
+           If anyone can figure it out, please be my guest (ramonpeek)*/
+		return 0;
+	}
+
 	/* Disable early RTP bridge  */
 	if (!ast_bridged_channel(chan) && !global_directrtpsetup) 	/* We are in early state */
 		return 0;
