Mortaza Kamal Nourestani posted here a way to ensure that mobile devices are served at a “m.” subdomain site, and that desktop devices are served at the normal domain.
Here’s my take on that using a resolver in the httprequest pipeline. This only requires adding a class, and .config file with no modifications to existing files. I’ve reused his IsMobileBrowser method.

using System;
using System.Linq;
using System.Web;
using Sitecore.Pipelines.HttpRequest;

namespace Samples.Extensions.Resolvers
{
    public class MobileSiteResolver : Sitecore.Pipelines.HttpRequest.SiteResolver
    {
        public override void Process(HttpRequestArgs args)
        {
            string absoluteUri = String.Format("{0}://{1}{2}", HttpContext.Current.Request.Url.Scheme,
                                                       HttpContext.Current.Request.Url.Host,
                                                       HttpContext.Current.Request.RawUrl);

            string host = HttpContext.Current.Request.Url.Host;

            if (host.StartsWith("m."))
            {
                if (!IsMobileBrowser(HttpContext.Current))
                {
                    host = host.Replace("m.", "");
                    absoluteUri = absoluteUri.Replace(HttpContext.Current.Request.Url.Host, host);
                    HttpContext.Current.Response.Redirect(absoluteUri);
                }
            }
            else
            {
                if (IsMobileBrowser(HttpContext.Current))
                {
                    host = String.Format("{0}.{1}", "m", HttpContext.Current.Request.Url.Host);
                    absoluteUri = absoluteUri.Replace(HttpContext.Current.Request.Url.Host, host);
                    HttpContext.Current.Response.Redirect(absoluteUri);
                }
            }
        }

        public static bool IsMobileBrowser(HttpContext context)
        {
            //FIRST TRY BUILT IN ASP.NT CHECK
            if (context.Request.Browser.IsMobileDevice)
            {
                return true;
            }
            //THEN TRY CHECKING FOR THE HTTP_X_WAP_PROFILE HEADER
            if (context.Request.ServerVariables["HTTP_X_WAP_PROFILE"] != null)
            {
                return true;
            }
            //THEN TRY CHECKING THAT HTTP_ACCEPT EXISTS AND CONTAINS WAP
            if (context.Request.ServerVariables["HTTP_ACCEPT"] != null &&
                context.Request.ServerVariables["HTTP_ACCEPT"].ToLower().Contains("wap"))
            {
                return true;
            }
            //AND FINALLY CHECK THE HTTP_USER_AGENT
            //HEADER VARIABLE FOR ANY ONE OF THE FOLLOWING
            if (context.Request.ServerVariables["HTTP_USER_AGENT"] != null)
            {
                //Create a list of all mobile types
                string[] mobiles =
                    {
                        "midp", "j2me", "avant", "docomo",
                        "novarra", "palmos", "palmsource",
                        "240x320", "opwv", "chtml",
                        "pda", "windows ce", "mmp/",
                        "blackberry", "mib/", "symbian",
                        "wireless", "nokia", "hand", "mobi",
                        "phone", "cdm", "up.b", "audio",
                        "SIE-", "SEC-", "samsung", "HTC",
                        "mot-", "mitsu", "sagem", "sony"
                        , "alcatel", "lg", "eric", "vx",
                        "NEC", "philips", "mmm", "xx",
                        "panasonic", "sharp", "wap", "sch",
                        "rover", "pocket", "benq", "java",
                        "pt", "pg", "vox", "amoi",
                        "bird", "compal", "kg", "voda",
                        "sany", "kdd", "dbt", "sendo",
                        "sgh", "gradi", "jb", "dddi",
                        "moto", "iphone"
                    };


                //Loop through each item in the list created above
                //and check if the header contains that text
                if (mobiles.Any(s => context.Request.ServerVariables["HTTP_USER_AGENT"].ToLower().Contains(s.ToLower())))
                    return true;

            }

            return false;
        }
    }
}

To enable this resolver create a config file in /app_config/includes/ such as mobiledeviceresolver.config with these content:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
    <sitecore>
        <pipelines>
            <httpRequestBegin>
                <processor patch:before="*[@type='Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel']"
                type="Samples.Extensions.Resolvers.MobileSiteResolver, Logica.Extensions"/>
            </httpRequestBegin>
        </pipelines>
    </sitecore>
</configuration>

The usual caveats apply, this is untested in a production environment, test throughly before using. It could also be significantly optimized for performance.