void writeAdditionalNandInit(){
	ALOGD("NAND boot, writing additional init commands to /dev/smd0");
	send_modem("AT@BRIC=0");
	msleep(300);
	send_modem("AT+CFUN=0");
	msleep(300);
	send_modem("AT+COPS=2");
	msleep(300);
}
void hackDeactivateData(void *data, size_t datalen, RIL_Token t)
{
	int err;
	char * cmd;
	char * cid;
	int fd,i,fd2;
	ATResponse *p_response = NULL;

	ALOGW("DeactivateData");

	cid = ((char **)data)[0];
	asprintf(&cmd, "AT+CGACT=0,%s", cid);
    send_modem(cmd);
    free(cmd);

    // kill monitor process
    ALOGD("Deactdata:killing monitor");
    kill(monitor_pid, SIGTERM);
    waitpid(monitor_pid, NULL, 0);
    monitor_pid = 0;

    // kill remaining pppd
    ALOGD("Deactdata:killing pppd");
	system("killall pppd");
	sleep(1);

	i=0;
	while((fd = open("/etc/ppp/ppp0.pid",O_RDONLY)) > 0) {
		if(i%5 == 0) {
			system("killall pppd");
		}
		close(fd);
		if(i>25)
			goto error;
		i++;
		sleep(1);
	}

	ALOGD("Deactdata done, waiting 10 sec to let pppd die");
    is_data_active = 0;

    sleep(10);

	RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
	return;

	error:
		RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
}
void* pppd_thread(void *param)
{
    LOGD("%s: pppd_thread enter", logtime());
    
    requestsWaitComplete("pppd_thread");
    
    pppd_pid = fork();
    if(pppd_pid == 0) {
        
        char buff[256];
        kill(getppid(), SIGSTOP); //stop stealing my mojo 
        
        int act=0;
        
        send_modem("AT+CGACT?");
        do {
            read_modem(buff, sizeof(buff));
            char* actpos=strstr(buff, "+CGACT: 1,");
            if(actpos!=NULL) act=atoi(actpos+10);
        }while(buff[0]!='0');
        
        if(act!=0) {
            kill(getppid(), SIGCONT);
            exit(202);
        }

        sprintf(buff, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", current_apn);
        send_modem(buff);
        read_modem(buff, sizeof(buff));
        
        send_modem("ATD*99***1#");
        //send_modem("AT+CGDATA=\"PPP\",1");
        while(read_modem(buff, sizeof(buff))>0 && buff[0]=='+');
        //read_modem(buff, sizeof(buff));
        
        kill(getppid(), SIGCONT);

        int atd=atoi(buff);
        if(atd!=1 && atd!=3) exit(201); 

        sleep(1);

        close_modem(); //close modem handle before we transform to pppd
        int err = execl("/system/bin/pppd", "pppd", "/dev/smd1", "local","nodetach", "defaultroute", "noipdefault", "usepeerdns", "user", current_user, "debug", NULL);
        LOGE("%s: PPPD EXEC FAILED (%d)", logtime(),err);
        exit(200);
    } else {
        LOGD("%s: pppd pid is %d", logtime(),pppd_pid);
        
        int status=0;
        time_t start = time(NULL);
        waitpid(pppd_pid, &status, 0);
        pppd_pid=0;
        int runTime = time(NULL)-start;
        LOGD("%s: PPPD DIED after %d seconds with status %d", logtime(), runTime, status);
        
        if(lastDataError==PDP_FAIL_ERROR_UNSPECIFIED && WIFEXITED(status)){
            switch(WEXITSTATUS(status))
            {
                case 1: lastDataError=PDP_FAIL_INSUFFICIENT_RESOURCES; break;
                case 2: lastDataError=PDP_FAIL_SERVICE_OPTION_NOT_SUPPORTED; break;
                case 3: 
                case 4:
                    lastDataError=PDP_FAIL_PROTOCOL_ERRORS; break;
                case 19: lastDataError=PDP_FAIL_USER_AUTHENTICATION; break;
            }
        }
        
        requestsWaitComplete("pppd_thread");
        send_modem("AT+CGACT=0,1"); 
        
        if(dataConnectionState==DATA_STATE_CONNECTED || dataConnectionState==DATA_STATE_CONNECTION_KILL) {
            dataConnectionState=DATA_STATE_DISCONNECTED;
            RIL_Data_Call_Response dataCall={ .cid=1, .active=0, .type="IP", .apn=current_apn, .address=current_addr };
            s_rilenv->OnUnsolicitedResponse(RIL_UNSOL_DATA_CALL_LIST_CHANGED, &dataCall, sizeof(RIL_Data_Call_Response));
        }
    }

    LOGD("%s: pppd_thread exit", logtime());
    return NULL;
}
void hackSetupData(char **data, size_t datalen, RIL_Token t)
{
	const char *apn;
	char *user = NULL;
	char *pass = NULL;
	char *cmd;
	char *userpass;
	int err;
	ATResponse *p_response = NULL;
	int fd, pppstatus,i,fd2;
	FILE *pppconfig;
	size_t cur = 0;
	ssize_t written, rlen;
	char status[32] = {0};
	char *buffer;
	long buffSize, len;
	int retry = 10;
	char *response[3] = { "1", "ppp0", "255.255.255.255" };
	int mypppstatus;
	int ret;
	struct termios  ios;

	ALOGW("hackSetupData(%s)\n",((const char **)data)[2]);

	apn = ((const char **)data)[2];
	user = ((char **)data)[3];
	if(user != NULL)
	{
		if (strlen(user)<2)
			user = "******";
	} else
		user = "******";

	pass = ((char **)data)[4];
	if(pass != NULL)
	{
		if (strlen(pass)<2)
			pass = "******";
	} else
		pass = "******";


	if(*data[0]=='0')
		ALOGD("Android want us to connect as CDMA while we are a GSM phone !");

    strcpy(current_apn, apn);
	asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", apn);
	//FIXME check for error here
	//err = at_send_command(cmd, NULL);
	send_modem(cmd);
	free(cmd);
	msleep(300);

	// Set required QoS params to default
	send_modem("AT+CGQREQ=1");
	msleep(300);
	// Set minimum QoS params to default
	send_modem("AT+CGQMIN=1");
	msleep(300);
	// packet-domain event reporting
	send_modem("AT+CGEREP=1,0");
	msleep(300);

	asprintf(&userpass, "%s * %s\n", user, pass);
	len = strlen(userpass);

	// if file does not exist we will create it
	system("touch /etc/ppp/pap-secrets");	
	fd = open("/etc/ppp/pap-secrets",O_WRONLY);
	if(fd < 0) {
		ALOGE("unable to open /etc/ppp/pap-secrets\n");
		goto error;
	}
	write(fd, userpass, len);
	close(fd);

	// if file does not exist we will create it
	system("touch /etc/ppp/chap-secrets");
	fd = open("/etc/ppp/chap-secrets",O_WRONLY);
	if(fd < 0) {
		ALOGE("unable to open /etc/ppp/chap-secrets\n");
		goto error;
	}
	write(fd, userpass, len);
	close(fd);
	free(userpass);

	// if file does not exist we will create it
	system("touch /etc/ppp/options.smd");
	pppconfig = fopen("/etc/ppp/options.smd","r");
	if(!pppconfig) {
		ALOGE("unable to open /etc/ppp/options.smd\n");
		goto error;
	}

	//filesize
	fseek(pppconfig, 0, SEEK_END);
	buffSize = ftell(pppconfig);
	rewind(pppconfig);

	//allocate memory
	buffer = (char *) malloc (sizeof(char)*buffSize);
	if (buffer == NULL) {
		ALOGE("hackSetupData: malloc buffer failed\n");
		goto error;
	}

	//read in the original file
	len = fread (buffer,1,buffSize,pppconfig);
	if (len != buffSize) {
		ALOGE("hackSetupData: fread failed\n");
		goto error;
	}
	fclose(pppconfig);

	// if file does not exist we will create it
	system("touch /etc/ppp/options.smd1");
	pppconfig = fopen("/etc/ppp/options.smd1","w");
	fwrite(buffer,1,buffSize,pppconfig);
	fprintf(pppconfig,"user %s\n",user);
	fclose(pppconfig);
	free(buffer);

	ALOGW("launching pppd\n");
    is_data_active = 1;
    launch_pppd();

    // Give some time to launch pppd
	sleep(7);

	ALOGD("setupData exit\n");
	
	RIL_onRequestComplete(t, RIL_E_SUCCESS, response, sizeof(response));
	return;
	error:
		ALOGE("PL:hackSetupData: ERROR ?");
		RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
}
void launch_pppd()
{
    int status;
    ALOGW("start mon");
    monitor_pid = fork();
    if(monitor_pid == 0) {
        time_t last_run, die_time;
        int failure_cnt = 0;
        // install signal handler to be notified of network avail
        signal(SIGUSR1, set_network_ready);
        signal(SIGUSR2, reset_network_ready);

        // exit signals to debug zombie problem
        signal(SIGINT, sigint_signal);
        signal(SIGTERM, sigterm_signal);
        signal(SIGQUIT, sigquit_signal);
        while(1) {
            ALOGW("Mon: start pppd (net=%d)", is_network_ready);
            if(!is_network_ready) {
                ALOGW("net not ready, waiting");
                sleep(1);
            }
            else {
                int err;
                time(&last_run);
                pppd_pid = fork();
                if(pppd_pid == 0) {
                    ALOGD("atd+ppd");
                    send_modem("AT+CGACT=0,1");
                    msleep(300);
                    send_modem("ATD*99***1#");

                    // The modem replies immediately even if it's not connected!
                    // so wait a short time.
                    sleep(3);
                    err = execl("/system/bin/pppd", "/system/bin/pppd", "nodetach", "/dev/smd1", "defaultroute", "debug", (char *)0);
                    ALOGE("PPPD EXEC FAILED (%d)", err);
                }
                else {
                    ALOGD("pppd pid is %d", pppd_pid);
                    while(wait(&status) != pppd_pid)
                        ALOGD("PL:wait:%d", status);
                    ALOGW("PPPD DIED! (0x%x)", status);
                    time(&die_time);
                    if(die_time - last_run < 5) {
                        // pppd died in less than 5 seconds
                        failure_cnt++;
                        if(failure_cnt > 3) {
                            ALOGD("fail cnt=%d", failure_cnt);
                            // atd won't cut it, slow down respawn
                            sleep(5 * failure_cnt);
                        } else if(failure_cnt == 5) {
                            char *cmd;
                            // we waited long enough, let be more radical
                            ALOGE("too much retries, full restart");
                            asprintf(&cmd, "AT+CGDCONT=1,\"IP\",\"%s\",,0,0", current_apn);
                            send_modem(cmd);
                            free(cmd);
                            msleep(300);
                        } else if(failure_cnt > 5) {
                            // nothing does it, don't hammer modem
                            ALOGE("full restart doesn't cut it, giving up");
                            sleep(30);
                        }
                    }
                    else {
                        failure_cnt = 1;
                    }
                    sleep(3);
                }
            }
        }
    }
}