static void gps_nmea_thread( void* arg ) { GpsState *state = (GpsState *)arg; NmeaReader *reader; reader = &state->reader; DFR("gps entered nmea thread"); int versioncnt = 0; // now loop while (continue_thread) { char buf[512]; int nn, ret; struct timeval tv; while(sleep_lock == 0 && continue_thread) //don't read while sleep sleep(1); if(state->fd == -1) { GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_END); gps_opentty(state); sleep(1); continue; } if(bOrionShutdown && started) // Orion be shutdown but LM is started, try to wake it up. { ALOGI("Try to wake orion up after 5 secs"); sleep_lock = 0; sleep(5); GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_BEGIN); gps_wakeup(state); nmea_reader_init( reader ); bOrionShutdown = 0; } if(!continue_thread) break; fd_set readfds; FD_ZERO(&readfds); FD_SET(state->fd, &readfds); /* Wait up to 100 ms. */ tv.tv_sec = 0; tv.tv_usec = 100; ret = select(state->fd + 1, &readfds, NULL, NULL, &tv); if (FD_ISSET(state->fd, &readfds)) { memset(buf,0,sizeof(buf)); ret = read( state->fd, buf, sizeof(buf) ); if (ret > 0) { if (strstr(buf, "CFG_R")) { ALOGI("ver %s",buf); } for (nn = 0; nn < ret; nn++) nmea_reader_addc( reader, buf[nn] ); /* ATHR in/out sentences*/ if ((buf[0] == 'O') && (buf[1] == 'A') && (buf[2] == 'P')) { D("OAP200 sentences found"); athr_reader_parse(buf, ret); /* for (nn = 0; nn < ret; nn++) D("%.2x ", buf[nn]); */ }else if ((buf[0] == '#') && (buf[1] == '!') && \ (buf[2] == 'G') && (buf[3] == 'S') && \ (buf[4] == 'M') && (buf[5] == 'A')) { D("GSMA sentences found"); athr_reader_parse(buf, ret); } } else { DFR("Error on NMEA read :%s",strerror(errno)); gps_closetty(state); GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_END); sleep(3); //wait Orion shutdown. bOrionShutdown = 1; continue; } } if(!continue_thread) break; } Exit: DFR("gps nmea thread destroyed"); return; }
/* this is the main thread, it waits for commands from gps_state_start/stop and, * when started, messages from the QEMU GPS daemon. these are simple NMEA sentences * that must be parsed to be converted into GPS fixes sent to the framework */ static void gps_state_thread( void* arg ) { GpsState* state = (GpsState*) arg; NmeaReader reader[1]; int epoll_fd = epoll_create(2); int started = 0; int gps_fd = state->fd; int control_fd = state->control[1]; nmea_reader_init( reader ); // register control file descriptors for polling epoll_register( epoll_fd, control_fd ); epoll_register( epoll_fd, gps_fd ); D("gps thread running"); // now loop for (;;) { struct epoll_event events[2]; int ne, nevents; nevents = epoll_wait( epoll_fd, events, 2, -1 ); if (nevents < 0) { if (errno != EINTR) LOGE("epoll_wait() unexpected error: %s", strerror(errno)); continue; } D("gps thread received %d events", nevents); for (ne = 0; ne < nevents; ne++) { if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) { LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?"); return; } if ((events[ne].events & EPOLLIN) != 0) { int fd = events[ne].data.fd; if (fd == control_fd) { char cmd = 255; int ret; D("gps control fd event"); do { ret = read( fd, &cmd, 1 ); } while (ret < 0 && errno == EINTR); if (cmd == CMD_QUIT) { D("gps thread quitting on demand"); return; } else if (cmd == CMD_START) { if (!started) { D("gps thread starting location_cb=%p", state->callbacks.location_cb); started = 1; nmea_reader_set_callback( reader, state->callbacks.location_cb ); state->init = 1; /*char testbuf[100]; int nn; sprintf(testbuf,"%s",GPS_TestData); for (nn = 0; nn < strlen(testbuf); nn++) { nmea_reader_addc( reader, testbuf[nn]); }*/ } } else if (cmd == CMD_STOP) { if (started) { D("gps thread stopping"); started = 0; nmea_reader_set_callback( reader, NULL ); } } } else if (fd == gps_fd) { char buff[32]; D("gps fd event"); for (;;) { int nn, ret; ret = read( fd, buff, sizeof(buff) ); if (ret < 0) { if (errno == EINTR) continue; if (errno != EWOULDBLOCK) LOGE("error while reading from gps daemon socket: %s:", strerror(errno)); break; } D("received %d bytes: %.*s", ret, ret, buff); for (nn = 0; nn < ret; nn++) nmea_reader_addc( reader, buff[nn] ); } D("gps fd event end"); } else { LOGE("epoll_wait() returned unkown fd %d ?", fd); } } } } }
static void gps_state_thread( void* arg ) { GpsState* state = (GpsState*) arg; int gps_fd = state->fd; int control_fd = state->control[1]; epoll_ctrlfd = epoll_create(1); epoll_nmeafd = epoll_create(1); // register control file descriptors for polling epoll_register( epoll_ctrlfd, control_fd ); D("gps thread running"); state->tmr_thread = state->callbacks.create_thread_cb("athr_gps_tmr", gps_timer_thread, state); if (!state->tmr_thread) { ALOGE("could not create gps timer thread: %s", strerror(errno)); started = 0; state->init = STATE_INIT; goto Exit; } state->nmea_thread = state->callbacks.create_thread_cb("athr_nmea_thread", gps_nmea_thread, state); if (!state->nmea_thread) { ALOGE("could not create gps nmea thread: %s", strerror(errno)); started = 0; state->init = STATE_INIT; goto Exit; } started = 0; state->init = STATE_INIT; // now loop for (;;) { struct epoll_event events[1]; int ne, nevents; nevents = epoll_wait( epoll_ctrlfd, events, 1, -1 ); if (nevents < 0) { if (errno != EINTR) ALOGE("epoll_wait() unexpected error: %s", strerror(errno)); continue; } // D("gps thread received %d events", nevents); for (ne = 0; ne < nevents; ne++) { if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) { ALOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?"); goto Exit; } if ((events[ne].events & EPOLLIN) != 0) { int fd = events[ne].data.fd; if (fd == control_fd) { char cmd = 255; int ret; D("gps control fd event"); do { ret = read( fd, &cmd, 1 ); } while (ret < 0 && errno == EINTR); if (cmd == CMD_QUIT) { D("gps thread quitting on demand"); goto Exit; } else if (cmd == CMD_START) { if (!started) { NmeaReader *reader; reader = &state->reader; nmea_reader_init( reader ); D("gps thread starting location_cb=%p", state->callbacks.location_cb); started = 1; state->init = STATE_START; /* handle wakeup routine*/ gps_wakeup(state); } else D("LM already start"); } else if (cmd == CMD_STOP) { if (started) { state->init = STATE_INIT; } } } else { ALOGE("epoll_wait() returned unkown fd %d ?", fd); gps_fd = _gps_state->fd; //resign fd to gps_fd } } } } Exit: { void *dummy; continue_thread = 0; close(epoll_ctrlfd); close(epoll_nmeafd); pthread_join(state->tmr_thread, &dummy); pthread_join(state->nmea_thread, &dummy); DFR("gps control thread destroyed"); } return; }