tty上网行规的设置

目的

AP/BP通过shared memory上网, shared memory虚拟成多个tty端口,通过其中一个tty端口上网,

上网端口的行规设置为 N_PPP,在kernel一直没有找到哪里设置了这个行规。在哪里设置的哪?

从系统调用的接口开始跟踪:看那个进程调用了这只行规的函数。

long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    case TIOCSETD:
        return tiocsetd(tty, p);
}
static int tiocsetd(struct tty_struct *tty, int __user *p)
{
    int ldisc;
    int ret;

    if (get_user(ldisc, p))
        return -EFAULT;
    pr_err("tiocsetd: where set N_PPP=3 from %d to %d\n", tty->ldisc->ops->num, ldisc);
    BUG_ON(1);
    ret = tty_set_ldisc(tty, ldisc);

    return ret;
}

/************************************************************************/

通过上面的bug_on可以找到当前的进程:pppd

pppd应用程序是怎样运行的?

从android/device/xxx/yyy/init.rc中可以找到
#telink add for pppd           
    chown root shell /system/xbin/ppp_gprs0.sh
    chown root shell /system/xbin/ppp_gprs1.sh
    chmod 0777 /system/xbin/ppp_gprs0.sh
    chmod 0777 /system/xbin/ppp_gprs1.sh
service pppd-ppp0 /system/xbin/ppp_gprs0.sh
    class main                                
    user root                                 
    group radio cache inet misc audio sdcard_rw log
    disabled                            
    oneshot
                                                                         
service pppd-ppp1 /system/xbin/ppp_gprs1.sh
    class main                
    user root                                                          
    group radio cache inet misc audio sdcard_rw log                        
    disabled                 
    oneshot

可以找到:/common/pre-built/tl7689/ril/ppp_gprs0.sh

ppp_gprs0.sh的内容为:

#!/system/bin/sh

USER0=`/system/bin/getprop net.gprs.user0`
PASSWORD0=`/system/bin/getprop net.gprs.password0`
DEVICE0=`/system/bin/getprop net.gprs.device0`

#USER0='/system/bin/getprop net.gprs.user0'
#PASSWORD0='/system/bin/getprop net.gprs.password0'
#DEVICE0='/system/bin/getprop net.gprs.device0'
#/system/bin/setprop net.gprs.ppp-exit ""
/system/bin/pppd $DEVICE0 115200 crtscts noauth debug nodetach usepeerdns noipdefault defaultroute user $USER0 password $PASSWORD0 ipcp-accept-local ipcp-accept-remote linkname ppp0
#/system/bin/pppd -detach $DEVICE 115200 noipdefault noauth debug novj usepeerdns noccp ipcp-no-addresses kdebug 4 defaultroute user $USER password $PASSWORD
#/system/bin/setprop net.gprs.ppp-exit $?
#exit $?

# $DEVICE0等是函数的参数,它是通过getprop net.gprs.device0得到的;

下面搜索net.gprs.device0:

property_set("net.gprs.device0","/dev/ttyN1");
void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
{
    const char *apn, *user, *pass;
    char *auth;

    apn = ((const char **) data)[2];
    user = ((const char **) data)[3];
    pass = ((const char **) data)[4];
    auth = strdup(((const char **) data)[5]);
    //type = getNWType(((const char **) data)[6]);
    type = strdup(((const char **) data)[6]);
    if(type == NULL) type = "IP";

    if(ppp_connection[0].isConnected == 0){
        LOGD("use ppp0 ===pppd service===");
        connect_cid = 1;
        strcpy(type_0,type);
        property_set("net.gprs.device0","/dev/ttyN1");
        if(user != NULL && pass != NULL){
            property_set("net.gprs.user0", user);
            property_set("net.gprs.password0",pass);
        }
    }else if(ppp_connection[0].isConnected != 0 && ppp_connection[1].isConnected == 0){
        LOGD("use ppp1 ===pppd service===");
        connect_cid = 2;
        strcpy(type_1,type);
        property_set("net.gprs.device1","/dev/ttyN4");
        if(user != NULL && pass != NULL){
            property_set("net.gprs.user1", user);
            property_set("net.gprs.password1",pass);
        }
    }
}

哪里启动了这个server?

service pppd-ppp0 /system/xbin/ppp_gprs0.sh
void *startPpp0Attach(void *param){
    property_set("ctl.start", "pppd-ppp0");  
}
/*
*蓝牙模块中一个比较核心的文件是bluetooth.c, 在我们上电的时候, 会调用这个文件中bt_enable()这个函数, 在这个函数里面*先调用set_bluetooth_power()上电,然后调用property_set("ctl.start", "hciattach"), 去启动hciattach这个服务,从而*运行brcm_patchram_plus这个进程。这个服务会加载我们firmware等一些工作。这部分工作做完后, 我们会调用property_set* *("ctl.start","bluetoothd"),这个服务是启动我们的bluz进程。如果以上成功的话,蓝牙芯片将会开始工作。
*/


哪里设置了ttyNx discipline?

/********************************************************************
 *
 * tty_establish_ppp - Turn the serial port into a ppp interface.
 */

int tty_establish_ppp (int tty_fd)
{
    int ret_fd;
    ioctl(tty_fd, TIOCSETD, &ppp_disc);
    generic_establish_ppp(tty_fd);
}

/********************************************************************
 * 哪里设置了tty_fd? 我们可以从调用函数的地方入手
 */
void
link_required(unit)
    int unit;
{
    new_phase(PHASE_SERIALCONN);
    /*devfd来自connect函数*/
    devfd = the_channel->connect()
;
    if (devfd < 0)
    goto fail;

    /* set up the serial device as a ppp interface */
    /*
     * N.B. we used to do tdb_writelock/tdb_writeunlock around this
     * (from establish_ppp to set_ifunit).  However, we won't be
     * doing the set_ifunit in multilink mode, which is the only time
     * we need the atomicity that the tdb_writelock/tdb_writeunlock
     * gives us.  Thus we don't need the tdb_writelock/tdb_writeunlock.
     */
    fd_ppp = the_channel->establish_ppp(devfd);

}

the_channel来自哪里?


void tty_init()
{
    add_notifier(&pidchange, maybe_relock, 0);
    the_channel = &tty_channel;
    xmit_accm[3] = 0x60000000;
}
struct channel tty_channel = {
    tty_options,
    &tty_process_extra_options,
    &tty_check_options,
    &connect_tty,
    &disconnect_tty,
    &tty_establish_ppp,
    &tty_disestablish_ppp,
    &tty_do_send_config,
    &tty_recv_config,
    &cleanup_tty,
    &tty_close_fds
};

/*
 * connect_tty - get the serial port ready to start doing PPP.
 * That is, open the serial port, set its speed and mode, and run
 * the connector and/or welcomer.
 
*/
int connect_tty()
{
    if (devnam[0] != 0) {
        for (;;) {
            real_ttyfd = open(devnam, O_NONBLOCK | O_RDWR, 0);
            if (real_ttyfd >= 0)
                break;

        }
        ttyfd = real_ttyfd;
        /*
         * Set line speed, flow control, etc.
         * If we have a non-null connection or initializer script,
         * on most systems we set CLOCAL for now so that we can talk
         * to the modem before carrier comes up.  But this has the
         * side effect that we might miss it if CD drops before we
         * get to clear CLOCAL below.  On systems where we can talk
         * successfully to the modem with CLOCAL clear and CD down,
         * we could clear CLOCAL at this point.
         */
        set_up_tty(ttyfd, ((connector != NULL && connector[0] != 0)
                   || initializer != NULL));
    }

}

devnam来自哪里

devnam是个全局变量,哪里赋的值?

pppd入口


int
main(argc, argv)
    int argc;
    char *argv[];
{
    /*
     * Initialize each protocol.
     */
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
        (*protp->init)(0);

    /*
     * Initialize the default channel.
     */
    tty_init();
    parse_args(argc-1, argv+1);

   lcp_open(0);        /* Start protocol */

}

分析程序的输入参数

/*

 * parse_args - parse a string of arguments from the command line.
 */
int
parse_args(argc, argv)
    int argc;
    char **argv;
{
    char *arg;
    option_t *opt;
    opt = find_option(arg);
    n = n_arguments(opt);
    process_option(opt, arg, argv);
}

/* option descriptors */
option_t tty_options[] = {
    /* device name must be first, or change connect_tty() below! */
    { "device name", o_wild, (void *) &setdevname,
      "Serial port device name",
      OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG  | OPT_A2STRVAL | OPT_STATIC,
      devnam},
}

/*
 * setdevname - Set the device name.
 * If doit is 0, the call is to check whether this option is
 * potentially a device name.
 */
static int
setdevname(cp, argv, doit)
    char *cp;
    char **argv;
    int doit;
{
    if (doit) {
         strlcpy(devnam, cp, sizeof(devnam));
        devstat = statbuf;
        default_device = 0;
    }
 
    return 1;
}


总结

用过建立上网通道的代码分为两部分 ril/ pppd:

android/hardware/ril:

android/external/ppp:

ril会告诉pppd使用那个通过上网,并启动 pppd,而pppd会进而设置tty的行规。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值