static int writeCtrlZ(const char *s, RILChannelCtx *p_channel) { size_t cur = 0; size_t len = strlen(s); ssize_t written; if (p_channel->fd < 0 || p_channel->readerClosed > 0) return AT_ERROR_CHANNEL_CLOSED; RLOGD("AT> %s^Z\n", s); AT_DUMP(">* ", s, strlen(s)); /* the main string */ while (cur < len) { do written = write(p_channel->fd, s + cur, len - cur); while (written < 0 && errno == EINTR); if (written < 0) return AT_ERROR_GENERIC; cur += written; } /* the ^Z */ do { written = write(p_channel->fd, "\032", 1); } while ((written < 0 && errno == EINTR) || (written == 0)); if (written < 0) return AT_ERROR_GENERIC; return 0; }
static int writeTransparentMode (const char *s) { size_t cur = 0; size_t len; ssize_t written; size_t write_len = 0; struct atcontext *context = get_at_context(); ENTER; len = context->pdu_length; if (context->fd < 0 || context->readerClosed > 0) { EXIT; return AT_ERROR_CHANNEL_CLOSED; } MBMLOGD("AT> %s^Z\n", s); AT_DUMP( ">* ", s, strlen(s) ); /* The main string. */ while (cur < len) { do { usleep(AT_WRITE_DELAY); if ((len - cur) >= 256) write_len = 256; else write_len = len - cur; written = write (context->fd, s + cur, write_len); } while (written < 0 && errno == EINTR); if (written < 0) { MBMLOGE("%s, AT_ERROR_GENERIC, written=%d", __FUNCTION__, (int)written); EXIT; return AT_ERROR_GENERIC; } cur += written; } EXIT; return 0; }
/** * Sends string s to the radio with a \r appended. * Returns AT_ERROR_* on error, 0 on success. * * This function exists because as of writing, android libc does not * have buffered stdio. */ static int writeline (const char *s) { size_t cur = 0; size_t len; ssize_t written; char *cmd = NULL; struct atcontext *context = get_at_context(); ENTER; if (context->fd < 0 || context->readerClosed > 0) { EXIT; return AT_ERROR_CHANNEL_CLOSED; } MBMLOGD("AT(%d)> %s\n", context->fd, s); AT_DUMP( ">> ", s, strlen(s) ); len = asprintf(&cmd, "%s\r\n", s); /* The main string. */ while (cur < len) { do { usleep(AT_WRITE_DELAY); written = write (context->fd, cmd + cur, len - cur); } while (written < 0 && (errno == EINTR || errno == EAGAIN)); if (written < 0) { free(cmd); EXIT; return AT_ERROR_GENERIC; } cur += written; } free(cmd); EXIT; return 0; }
/** * Sends string s to the radio with a \r appended. * Returns AT_ERROR_* on error, 0 on success. * * This function exists because as of writing, android libc does not * have buffered stdio. */ static int writeline (const char *s) { size_t cur = 0; size_t len = strlen(s); char *cmd; ssize_t written; struct atcontext *ac = getAtContext(); if (ac->fd < 0 || ac->readerClosed > 0) { return AT_ERROR_CHANNEL_CLOSED; } ALOGD("AT(%d)> %s", ac->fd, s); AT_DUMP( ">> ", s, strlen(s) ); if (!(asprintf(&cmd, "%s\r", s))) { ALOGE("%s() Failed to allocate string", __func__); return AT_ERROR_GENERIC; } len++; /* The whole string. */ while (cur < len) { do { written = write (ac->fd, cmd + cur, len - cur); } while (written < 0 && errno == EINTR); if (written < 0) { free(cmd); return AT_ERROR_GENERIC; } cur += written; } free(cmd); return 0; }
static int writeCtrlZ (const char *s) { size_t cur = 0; size_t len = strlen(s); ssize_t written; char *w; int ret = 0; if (s_fd < 0 || s_readerClosed > 0) { return AT_ERROR_CHANNEL_CLOSED; } LOGD("AT> %s^Z\n", s); AT_DUMP( ">* ", s, len ); w = malloc(len+1); if (!w) return AT_ERROR_GENERIC; strcpy(w, s); w[len] = '\032'; len++; /* the main string */ while (cur < len) { do { written = write (s_fd, w + cur, len - cur); } while (written < 0 && errno == EINTR); if (written < 0) { ret = AT_ERROR_GENERIC; break; } cur += written; } free(w); return ret; }
static int writeline (const char *s) { size_t cur = 0; size_t len = strlen(s); ssize_t written; if (s_fd < 0 || s_readerClosed > 0) { return AT_ERROR_CHANNEL_CLOSED; } if (!is_hide) LOGD("AT> %s\n", s); AT_DUMP( ">> ", s, strlen(s) ); /* the main string */ while (cur < len) { do { written = write (s_fd, s + cur, len - cur); } while (written < 0 && errno == EINTR); if (written < 0) { return AT_ERROR_GENERIC; } cur += written; } /* the \r */ do { written = write (s_fd, "\r" , 1); } while ((written < 0 && errno == EINTR) || (written == 0)); if (written < 0) { return AT_ERROR_GENERIC; } return 0; }
static const char *readline() { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret; /* this is a little odd. I use *s_ATBufferCur == 0 to * mean "buffer consumed completely". If it points to a character, than * the buffer continues until a \0 */ if (*s_ATBufferCur == '\0') { /* empty buffer */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* there's data in the buffer from the last read */ // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); if (p_eol == NULL) { /* a partial line. move it up and prepare to read more */ size_t len; len = strlen(s_ATBufferCur); memmove(s_ATBuffer, s_ATBufferCur, len + 1); p_read = s_ATBuffer + len; s_ATBufferCur = s_ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line */ /* that will be returned the while () loop below */ } while (p_eol == NULL) { if (0 == MAX_AT_RESPONSE - (p_read - s_ATBuffer)) { LOGE("ERROR: Input line exceeded buffer\n"); /* ditch buffer and start over again */ s_ATBufferCur = s_ATBuffer; *s_ATBufferCur = '\0'; p_read = s_ATBuffer; } do { count = read(s_fd, p_read, MAX_AT_RESPONSE - (p_read - s_ATBuffer)); } while (count < 0 && errno == EINTR); if (count > 0) { AT_DUMP( "<< ", p_read, count ); s_readCount += count; p_read[count] = '\0'; // skip over leading newlines while (*s_ATBufferCur == '\r' || *s_ATBufferCur == '\n') s_ATBufferCur++; p_eol = findNextEOL(s_ATBufferCur); p_read += count; } else if (count <= 0) { /* read error encountered or EOF reached */ if(count == 0) { LOGD("atchannel: EOF reached"); } else { LOGD("atchannel: read error %s", strerror(errno)); } return NULL; } } /* a full line in the buffer. Place a \0 over the \r and return */ ret = s_ATBufferCur; *p_eol = '\0'; s_ATBufferCur = p_eol + 1; /* this will always be <= p_read, */ /* and there will be a \0 at *p_read */ LOGD("AT< %s\n", ret); return ret; }
static const char *readline(void) { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret = NULL; struct atcontext *ac = getAtContext(); read(ac->fd,NULL,0); /* This is a little odd. I use *s_ATBufferCur == 0 to mean * "buffer consumed completely". If it points to a character, * then the buffer continues until a \0. */ if (*ac->ATBufferCur == '\0') { /* Empty buffer. */ ac->ATBufferCur = ac->ATBuffer; *ac->ATBufferCur = '\0'; p_read = ac->ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* There's data in the buffer from the last read. */ /* skip over leading newlines */ while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n') ac->ATBufferCur++; p_eol = findNextEOL(ac->ATBufferCur); if (p_eol == NULL) { /* A partial line. Move it up and prepare to read more. */ size_t len; len = strlen(ac->ATBufferCur); memmove(ac->ATBuffer, ac->ATBufferCur, len + 1); p_read = ac->ATBuffer + len; ac->ATBufferCur = ac->ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line that will be returned from the while () loop below. */ } while (p_eol == NULL) { int err; struct pollfd pfds[2]; /* This condition should be synchronized with the read function call * size argument below. */ if (0 >= MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2) { ALOGE("%s() ERROR: Input line exceeded buffer", __func__); /* Ditch buffer and start over again. */ ac->ATBufferCur = ac->ATBuffer; *ac->ATBufferCur = '\0'; p_read = ac->ATBuffer; } /* If our fd is invalid, we are probably closed. Return. */ if (ac->fd < 0) return NULL; pfds[0].fd = ac->fd; pfds[0].events = POLLIN | POLLERR; pfds[1].fd = ac->readerCmdFds[0]; pfds[1].events = POLLIN; err = poll(pfds, 2, -1); if (err < 0) { ALOGE("%s() poll: error: %s", __func__, strerror(errno)); return NULL; } if (pfds[1].revents & POLLIN) { char buf[10]; /* Just drain it. We don't care, this is just for waking up. */ read(pfds[1].fd, &buf, 1); continue; } if (pfds[0].revents & POLLERR) { ALOGE("%s() POLLERR event! Returning...", __func__); return NULL; } if (!(pfds[0].revents & POLLIN)) continue; do /* The size argument should be synchronized to the ditch buffer * condition above. */ count = read(ac->fd, p_read, MAX_AT_RESPONSE - (p_read - ac->ATBuffer) - 2); while (count < 0 && errno == EINTR); if (count > 0) { AT_DUMP( "<< ", p_read, count ); ac->readCount += count; /* Implementation requires extra EOS or EOL to get it right if * there are no trailing newlines in the read buffer. Adding extra * EOS does not harm even if there actually were trailing EOLs. */ p_read[count] = '\0'; p_read[count+1] = '\0'; /* Skip over leading newlines. */ while (*ac->ATBufferCur == '\r' || *ac->ATBufferCur == '\n') ac->ATBufferCur++; p_eol = findNextEOL(ac->ATBufferCur); p_read += count; } else if (count <= 0) { /* Read error encountered or EOF reached. */ if (count == 0) ALOGD("%s() atchannel: EOF reached.", __func__); else ALOGD("%s() atchannel: read error %s", __func__, strerror(errno)); return NULL; } } /* A full line in the buffer. Place a \0 over the \r and return. */ ret = ac->ATBufferCur; *p_eol = '\0'; /* The extra EOS added after read takes care of the case when there is no * valid data after p_eol. */ ac->ATBufferCur = p_eol + 1; /* This will always be <= p_read, and there will be a \0 at *p_read. */ ALOGI("AT(%d)< %s", ac->fd, ret); return ret; }
static const char *readline(void) { ssize_t count; char *p_read = NULL; char *p_eol = NULL; char *ret = NULL; struct atcontext *context = get_at_context(); ENTER; read(context->fd,NULL,0); /* This is a little odd. I use *s_ATBufferCur == 0 to mean * "buffer consumed completely". If it points to a character, * then the buffer continues until a \0. */ if (*context->ATBufferCur == '\0') { /* Empty buffer. */ context->ATBufferCur = context->ATBuffer; *context->ATBufferCur = '\0'; p_read = context->ATBuffer; } else { /* *s_ATBufferCur != '\0' */ /* There's data in the buffer from the last read. */ /* skip over leading newlines */ while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n') context->ATBufferCur++; p_eol = findNextEOL(context->ATBufferCur); if (p_eol == NULL) { /* A partial line. Move it up and prepare to read more. */ size_t len; len = strlen(context->ATBufferCur); memmove(context->ATBuffer, context->ATBufferCur, len + 1); p_read = context->ATBuffer + len; context->ATBufferCur = context->ATBuffer; } /* Otherwise, (p_eol !- NULL) there is a complete line that will be returned from the while () loop below. */ } while (p_eol == NULL) { int err; struct pollfd pfds[2]; if (0 >= MAX_AT_RESPONSE - (p_read - context->ATBuffer)) { MBMLOGE("%s() ERROR: Input line exceeded buffer", __FUNCTION__); /* Ditch buffer and start over again. */ context->ATBufferCur = context->ATBuffer; *context->ATBufferCur = '\0'; p_read = context->ATBuffer; } /* If our fd is invalid, we are probably closed. Return. */ if (context->fd < 0) { EXIT; return NULL; } pfds[0].fd = context->fd; pfds[0].events = POLLIN | POLLERR; pfds[1].fd = context->readerCmdFds[0]; pfds[1].events = POLLIN; err = poll(pfds, 2, -1); if (err < 0) { MBMLOGE("%s() poll: error: %s", __FUNCTION__, strerror(errno)); EXIT; return NULL; } if (pfds[1].revents & POLLIN) { char buf[10]; /* Just drain it. We don't care, this is just for waking up. */ read(pfds[1].fd, &buf, 1); continue; } if (pfds[0].revents & POLLERR) { MBMLOGE("POLLERR! Returning.."); EXIT; return NULL; } if (!(pfds[0].revents & POLLIN)) { continue; } do { count = read(context->fd, p_read, MAX_AT_RESPONSE - (p_read - context->ATBuffer)); } while (count < 0 && ((errno == EINTR) || (errno == EAGAIN))); if (count > 0) { AT_DUMP( "<< ", p_read, count ); context->readCount += count; p_read[count] = '\0'; /* Skip over leading newlines. */ while (*context->ATBufferCur == '\r' || *context->ATBufferCur == '\n') context->ATBufferCur++; p_eol = findNextEOL(context->ATBufferCur); p_read += count; } else if (count <= 0) { /* Read error encountered or EOF reached. */ if (count == 0) { MBMLOGE("%s() atchannel: EOF reached.", __FUNCTION__); } else { MBMLOGE("%s() atchannel: read error %s", __FUNCTION__, strerror(errno)); } EXIT; return NULL; } } /* A full line in the buffer. Place a \0 over the \r and return. */ ret = context->ATBufferCur; *p_eol = '\0'; context->ATBufferCur = p_eol + 1; /* This will always be <= p_read, and there will be a \0 at *p_read. */ MBMLOGD("AT(%d)< %s", context->fd, ret); EXIT; return ret; }
static void * mainLoop(void *param) { int fd; int ret; char path[50]; int ttys_index; AT_DUMP("== ", "entering mainLoop()", -1 ); at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); for (;;) { fd = -1; while (fd < 0) { if (s_port > 0) { fd = socket_loopback_client(s_port, SOCK_STREAM); } else if (s_device_socket) { if (!strcmp(s_device_path, "/dev/socket/qemud")) { /* Qemu-specific control socket */ fd = socket_local_client( "qemud", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM ); if (fd >= 0 ) { char answer[2]; if ( write(fd, "gsm", 3) != 3 || read(fd, answer, 2) != 2 || memcmp(answer, "OK", 2) != 0) { close(fd); fd = -1; } } } else fd = socket_local_client( s_device_path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM ); } else if (s_device_path != NULL) { fd = open (s_device_path, O_RDWR); if ( fd >= 0 && !memcmp( s_device_path, "/dev/ttyS", 9 ) ) { /* disable echo on serial ports */ struct termios ios; tcgetattr( fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr( fd, TCSANOW, &ios ); } } if (fd < 0) { perror ("opening AT interface. retrying..."); sleep(10); /* never returns */ } } RLOGD("FD: %d", fd); s_closed = 0; ret = at_open(fd, onUnsolicited); if (ret < 0) { RLOGE ("AT error %d on at_open\n", ret); return 0; } RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0); // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism sleep(1); waitForClose(); RLOGI("Re-opening after close"); } }
static void * mainLoop(void *param) { AT_DUMP("== ", "entering mainLoop()", -1 ); at_set_on_reader_closed(onATReaderClosed); at_set_on_timeout(onATTimeout); initRILChannels(); RLOGI("[Emu]mainloop_in"); RLOGI("[Emu]mainloop_in %d\n",s_device_socket); if(s_device_socket) { emulator_gemini_opensocket(); return NULL; } else { int ret; int i; RILChannelCtx * p_channel; for (;;) { for (i=0; i < RIL_SUPPORT_CHANNELS; i ++) { p_channel = getChannelCtxbyId(i); while (p_channel->fd < 0) { do { p_channel->fd = open(s_mux_path[i], O_RDWR); } while (p_channel->fd < 0 && errno == EINTR); if (p_channel->fd < 0) { perror ("opening AT interface. retrying..."); RLOGE("could not connect to %s: %s", s_mux_path[i], strerror(errno)); sleep(10); /* never returns */ } else { struct termios ios; tcgetattr(p_channel->fd, &ios ); ios.c_lflag = 0; /* disable ECHO, ICANON, etc... */ ios.c_iflag = 0; tcsetattr(p_channel->fd, TCSANOW, &ios ); } } s_closed = 0; ret = at_open(p_channel->fd,onUnsolicited, p_channel); if (ret < 0) { RLOGE ("AT error %d on at_open\n", ret); return 0; } } RIL_requestTimedCallback(initializeCallback, &s_pollSimId, &TIMEVAL_0); #ifdef MTK_GEMINI RIL_requestTimedCallback(initializeCallback, &s_pollSimId2, &TIMEVAL_0); #endif // Give initializeCallback a chance to dispatched, since // we don't presently have a cancellation mechanism sleep(1); waitForClose(); RLOGI("Re-opening after close"); } } }