/****************************************************************************** @file util.c @brief some utils for this QCM tool. DESCRIPTION Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules. INITIALIZATION AND SEQUENCING REQUIREMENTS None. --------------------------------------------------------------------------- Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved. Quectel Wireless Solution Proprietary and Confidential. --------------------------------------------------------------------------- ******************************************************************************/ #include #if defined(__STDC__) #include #define __V(x) x #else #include #define __V(x) (va_alist) va_dcl #define const #define volatile #endif #include #include "QMIThread.h" static void setTimespecRelative(struct timespec *p_ts, long long msec) { struct timeval tv; gettimeofday(&tv, (struct timezone *) NULL); /* what's really funny about this is that I know pthread_cond_timedwait just turns around and makes this a relative time again */ p_ts->tv_sec = tv.tv_sec + (msec / 1000); p_ts->tv_nsec = (tv.tv_usec + (msec % 1000) * 1000L ) * 1000L; if (p_ts->tv_nsec >= 1000000000UL) { p_ts->tv_sec += 1; p_ts->tv_nsec -= 1000000000UL; } } int pthread_cond_timeout_np(pthread_cond_t *cond, pthread_mutex_t * mutex, unsigned msecs) { if (msecs != 0) { unsigned i; unsigned t = msecs/4; int ret = 0; if (t == 0) t = 1; for (i = 0; i < msecs; i += t) { struct timespec ts; setTimespecRelative(&ts, t); ret = pthread_cond_timedwait(cond, mutex, &ts); //to advoid system time change if (ret != ETIMEDOUT) { if(ret) dbg_time("ret=%d, msecs=%u, t=%u", ret, msecs, t); break; } } return ret; } else { return pthread_cond_wait(cond, mutex); } } void cond_setclock_attr(pthread_cond_t *cond, clockid_t clock) { #if 0 //very old uclibc do not support pthread_condattr_setclock /* set relative time, for pthread_cond_timedwait */ pthread_condattr_t attr; pthread_condattr_init (&attr); pthread_condattr_setclock(&attr, clock); pthread_cond_init(cond, &attr); pthread_condattr_destroy (&attr); #endif } const char * get_time(void) { static char time_buf[50]; struct timeval tv; time_t time; suseconds_t millitm; struct tm *ti; gettimeofday (&tv, NULL); time= tv.tv_sec; millitm = (tv.tv_usec + 500) / 1000; if (millitm == 1000) { ++time; millitm = 0; } ti = localtime(&time); sprintf(time_buf, "%02d-%02d_%02d:%02d:%02d:%03d", ti->tm_mon+1, ti->tm_mday, ti->tm_hour, ti->tm_min, ti->tm_sec, (int)millitm); return time_buf; } unsigned long clock_msec(void) { struct timespec tm; clock_gettime( CLOCK_MONOTONIC, &tm); return (unsigned long)(tm.tv_sec*1000 + (tm.tv_nsec/1000000)); } FILE *logfilefp = NULL; const int i = 1; #define is_bigendian() ( (*(char*)&i) == 0 ) USHORT le16_to_cpu(USHORT v16) { USHORT tmp = v16; if (is_bigendian()) { unsigned char *s = (unsigned char *)(&v16); unsigned char *d = (unsigned char *)(&tmp); d[0] = s[1]; d[1] = s[0]; } return tmp; } UINT le32_to_cpu (UINT v32) { UINT tmp = v32; if (is_bigendian()) { unsigned char *s = (unsigned char *)(&v32); unsigned char *d = (unsigned char *)(&tmp); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } return tmp; } UINT ql_swap32(UINT v32) { UINT tmp = v32; { unsigned char *s = (unsigned char *)(&v32); unsigned char *d = (unsigned char *)(&tmp); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } return tmp; } USHORT cpu_to_le16(USHORT v16) { USHORT tmp = v16; if (is_bigendian()) { unsigned char *s = (unsigned char *)(&v16); unsigned char *d = (unsigned char *)(&tmp); d[0] = s[1]; d[1] = s[0]; } return tmp; } UINT cpu_to_le32 (UINT v32) { UINT tmp = v32; if (is_bigendian()) { unsigned char *s = (unsigned char *)(&v32); unsigned char *d = (unsigned char *)(&tmp); d[0] = s[3]; d[1] = s[2]; d[2] = s[1]; d[3] = s[0]; } return tmp; } void update_resolv_conf(int iptype, const char *ifname, const char *dns1, const char *dns2) { const char *dns_file = "/etc/resolv.conf"; FILE *dns_fp; char dns_line[256]; #define MAX_DNS 16 char *dns_info[MAX_DNS]; char dns_tag[64]; int dns_match = 0; int i; snprintf(dns_tag, sizeof(dns_tag), "# IPV%d %s", iptype, ifname); for (i = 0; i < MAX_DNS; i++) dns_info[i] = NULL; dns_fp = fopen(dns_file, "r"); if (dns_fp) { i = 0; dns_line[sizeof(dns_line)-1] = '\0'; while((fgets(dns_line, sizeof(dns_line)-1, dns_fp)) != NULL) { if ((strlen(dns_line) > 1) && (dns_line[strlen(dns_line) - 1] == '\n')) dns_line[strlen(dns_line) - 1] = '\0'; //dbg_time("%s", dns_line); if (strstr(dns_line, dns_tag)) { dns_match++; continue; } dns_info[i++] = strdup(dns_line); if (i == MAX_DNS) break; } fclose(dns_fp); } else if (errno != ENOENT) { dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); return; } if (dns1 == NULL && dns_match == 0) return; dns_fp = fopen(dns_file, "w"); if (dns_fp) { if (dns1) fprintf(dns_fp, "nameserver %s %s\n", dns1, dns_tag); if (dns2) fprintf(dns_fp, "nameserver %s %s\n", dns2, dns_tag); for (i = 0; i < MAX_DNS && dns_info[i]; i++) fprintf(dns_fp, "%s\n", dns_info[i]); fclose(dns_fp); } else { dbg_time("fopen %s fail, errno:%d (%s)", dns_file, errno, strerror(errno)); } for (i = 0; i < MAX_DNS && dns_info[i]; i++) free(dns_info[i]); } pid_t getpid_by_pdp(int pdp, const char* program_name) { glob_t gt; int ret; char filter[5] = {0}; pid_t pid; sprintf(filter, "-n %d", pdp); ret = glob("/proc/*/cmdline", GLOB_NOSORT, NULL, >); if (ret != 0) { dbg_time("glob error, errno = %d(%s)", errno, strerror(errno)); return -1; } else { int i = 0, fd = -1; size_t nreads; char cmdline[512] = {0}; for (i = 0; i < gt.gl_pathc; i++) { fd = open(gt.gl_pathv[i], O_RDONLY); if (fd == -1) { dbg_time("open %s failed, errno = %d(%s)", gt.gl_pathv[i], errno, strerror(errno)); globfree(>); return -1; } nreads = read(fd, cmdline, sizeof(cmdline)); if (nreads > 0) { int pos = 0; while (pos < nreads-1) { if (cmdline[pos] == '\0') cmdline[pos] = ' '; // space pos++; } // printf("%s\n", cmdline); } if (strstr(cmdline, program_name) && strstr(cmdline, filter)) { char path[64] = {0}; char pidstr[64] = {0}; char *p; dbg_time("%s: %s", gt.gl_pathv[i], cmdline); strcpy(path, gt.gl_pathv[i]); p = strstr(gt.gl_pathv[i], "/cmdline"); *p = '\0'; while (*(--p) != '/') ; strcpy(pidstr, p+1); pid = atoi(pidstr); globfree(>); return pid; } } } globfree(>); return -1; }