You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

947 lines
34 KiB

2 years ago
2 years ago
2 years ago
  1. /******************************************************************************
  2. @file main.c
  3. @brief The entry program.
  4. DESCRIPTION
  5. Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
  6. INITIALIZATION AND SEQUENCING REQUIREMENTS
  7. None.
  8. ---------------------------------------------------------------------------
  9. Copyright (c) 2016 -2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
  10. Quectel Wireless Solution Proprietary and Confidential.
  11. ---------------------------------------------------------------------------
  12. ******************************************************************************/
  13. #include "QMIThread.h"
  14. #include <sys/wait.h>
  15. #include <sys/utsname.h>
  16. #include <sys/time.h>
  17. #include <dirent.h>
  18. #include "util.h"
  19. //#define CONFIG_EXIT_WHEN_DIAL_FAILED
  20. //#define CONFIG_BACKGROUND_WHEN_GET_IP
  21. //#define CONFIG_PID_FILE_FORMAT "/var/run/quectel-CM-%s.pid" //for example /var/run/quectel-CM-wwan0.pid
  22. int debug_qmi = 0;
  23. int main_loop = 0;
  24. int qmidevice_control_fd[2];
  25. static int signal_control_fd[2];
  26. extern const struct qmi_device_ops gobi_qmidev_ops;
  27. extern const struct qmi_device_ops qmiwwan_qmidev_ops;
  28. extern int ql_ifconfig(int argc, char *argv[]);
  29. extern int ql_get_netcard_driver_info(const char*);
  30. extern int ql_capture_usbmon_log(PROFILE_T *profile, const char *log_path);
  31. extern void ql_stop_usbmon_log(PROFILE_T *profile);
  32. #ifdef CONFIG_BACKGROUND_WHEN_GET_IP
  33. static int daemon_pipe_fd[2];
  34. static void ql_prepare_daemon(void) {
  35. pid_t daemon_child_pid;
  36. if (pipe(daemon_pipe_fd) < 0) {
  37. dbg_time("%s Faild to create daemon_pipe_fd: %d (%s)", __func__, errno, strerror(errno));
  38. return;
  39. }
  40. daemon_child_pid = fork();
  41. if (daemon_child_pid > 0) {
  42. struct pollfd pollfds[] = {{daemon_pipe_fd[0], POLLIN, 0}, {0, POLLIN, 0}};
  43. int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]);
  44. int signo;
  45. //dbg_time("father");
  46. close(daemon_pipe_fd[1]);
  47. if (socketpair( AF_LOCAL, SOCK_STREAM, 0, signal_control_fd) < 0 ) {
  48. dbg_time("%s Faild to create main_control_fd: %d (%s)", __func__, errno, strerror(errno));
  49. return;
  50. }
  51. pollfds[1].fd = signal_control_fd[1];
  52. while (1) {
  53. do {
  54. ret = poll(pollfds, nevents, -1);
  55. } while ((ret < 0) && (errno == EINTR));
  56. if (ret < 0) {
  57. dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
  58. goto __daemon_quit;
  59. }
  60. for (ne = 0; ne < nevents; ne++) {
  61. int fd = pollfds[ne].fd;
  62. short revents = pollfds[ne].revents;
  63. if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
  64. //dbg_time("%s poll err/hup", __func__);
  65. //dbg_time("poll fd = %d, events = 0x%04x", fd, revents);
  66. if (revents & POLLHUP)
  67. goto __daemon_quit;
  68. }
  69. if ((revents & POLLIN) && read(fd, &signo, sizeof(signo)) == sizeof(signo)) {
  70. if (signal_control_fd[1] == fd) {
  71. if (signo == SIGCHLD) {
  72. int status;
  73. int pid = waitpid(daemon_child_pid, &status, 0);
  74. dbg_time("waitpid pid=%d, status=%x", pid, status);
  75. goto __daemon_quit;
  76. } else {
  77. kill(daemon_child_pid, signo);
  78. }
  79. } else if (daemon_pipe_fd[0] == fd) {
  80. //dbg_time("daemon_pipe_signo = %d", signo);
  81. goto __daemon_quit;
  82. }
  83. }
  84. }
  85. }
  86. __daemon_quit:
  87. //dbg_time("father exit");
  88. _exit(0);
  89. } else if (daemon_child_pid == 0) {
  90. close(daemon_pipe_fd[0]);
  91. //dbg_time("child", getpid());
  92. } else {
  93. close(daemon_pipe_fd[0]);
  94. close(daemon_pipe_fd[1]);
  95. dbg_time("%s Faild to create daemon_child_pid: %d (%s)", __func__, errno, strerror(errno));
  96. }
  97. }
  98. static void ql_enter_daemon(int signo) {
  99. if (daemon_pipe_fd[1] > 0)
  100. if (signo) {
  101. write(daemon_pipe_fd[1], &signo, sizeof(signo));
  102. sleep(1);
  103. }
  104. close(daemon_pipe_fd[1]);
  105. daemon_pipe_fd[1] = -1;
  106. setsid();
  107. }
  108. #endif
  109. //UINT ifc_get_addr(const char *ifname);
  110. static int s_link = -1;
  111. static void usbnet_link_state(int state)
  112. {
  113. s_link = state ? 1 : 0;
  114. }
  115. static void usbnet_link_change(int link, PROFILE_T *profile) {
  116. if (s_link == link)
  117. return;
  118. s_link = link;
  119. if (link) {
  120. udhcpc_start(profile);
  121. } else {
  122. udhcpc_stop(profile);
  123. }
  124. #ifdef CONFIG_BACKGROUND_WHEN_GET_IP
  125. if (link && daemon_pipe_fd[1] > 0) {
  126. int timeout = 6;
  127. while (timeout-- /*&& ifc_get_addr(profile->usbnet_adapter) == 0*/) {
  128. sleep(1);
  129. }
  130. ql_enter_daemon(SIG_EVENT_START);
  131. }
  132. #endif
  133. }
  134. static int check_ipv4_address(PROFILE_T *now_profile) {
  135. PROFILE_T new_profile_v;
  136. PROFILE_T *new_profile = &new_profile_v;
  137. memcpy(new_profile, now_profile, sizeof(PROFILE_T));
  138. if (requestGetIPAddress(new_profile, IpFamilyV4) == 0) {
  139. if (new_profile->ipv4.Address != now_profile->ipv4.Address || debug_qmi) {
  140. unsigned char *l = (unsigned char *)&now_profile->ipv4.Address;
  141. unsigned char *r = (unsigned char *)&new_profile->ipv4.Address;
  142. dbg_time("localIP: %d.%d.%d.%d VS remoteIP: %d.%d.%d.%d",
  143. l[3], l[2], l[1], l[0], r[3], r[2], r[1], r[0]);
  144. }
  145. return (new_profile->ipv4.Address == now_profile->ipv4.Address);
  146. }
  147. return 0;
  148. }
  149. static void main_send_event_to_qmidevice(int triger_event) {
  150. write(qmidevice_control_fd[0], &triger_event, sizeof(triger_event));
  151. }
  152. static void send_signo_to_main(int signo) {
  153. write(signal_control_fd[0], &signo, sizeof(signo));
  154. }
  155. void qmidevice_send_event_to_main(int triger_event) {
  156. write(qmidevice_control_fd[1], &triger_event, sizeof(triger_event));
  157. }
  158. void qmidevice_send_event_to_main_ext(int triger_event, void *data, unsigned len) {
  159. write(qmidevice_control_fd[1], &triger_event, sizeof(triger_event));
  160. write(qmidevice_control_fd[1], data, len);
  161. }
  162. #define MAX_PATH 256
  163. static int ls_dir(const char *dir, int (*match)(const char *dir, const char *file, void *argv[]), void *argv[])
  164. {
  165. DIR *pDir;
  166. struct dirent* ent = NULL;
  167. int match_times = 0;
  168. pDir = opendir(dir);
  169. if (pDir == NULL) {
  170. dbg_time("Cannot open directory: %s, errno: %d (%s)", dir, errno, strerror(errno));
  171. return 0;
  172. }
  173. while ((ent = readdir(pDir)) != NULL) {
  174. match_times += match(dir, ent->d_name, argv);
  175. }
  176. closedir(pDir);
  177. return match_times;
  178. }
  179. static int is_same_linkfile(const char *dir, const char *file, void *argv[])
  180. {
  181. const char *qmichannel = (const char *)argv[1];
  182. char linkname[MAX_PATH];
  183. char filename[MAX_PATH];
  184. int linksize;
  185. snprintf(linkname, MAX_PATH, "%s/%s", dir, file);
  186. linksize = readlink(linkname, filename, MAX_PATH);
  187. if (linksize <= 0)
  188. return 0;
  189. filename[linksize] = 0;
  190. if (strcmp(filename, qmichannel))
  191. return 0;
  192. dbg_time("%s -> %s", linkname, filename);
  193. return 1;
  194. }
  195. static int is_brother_process(const char *dir, const char *file, void *argv[])
  196. {
  197. //const char *myself = (const char *)argv[0];
  198. char linkname[MAX_PATH];
  199. char filename[MAX_PATH];
  200. int linksize;
  201. int i = 0, kill_timeout = 15;
  202. pid_t pid;
  203. //dbg_time("%s", file);
  204. while (file[i]) {
  205. if (!isdigit(file[i]))
  206. break;
  207. i++;
  208. }
  209. if (file[i]) {
  210. //dbg_time("%s not digit", file);
  211. return 0;
  212. }
  213. snprintf(linkname, MAX_PATH, "%s/%s/exe", dir, file);
  214. linksize = readlink(linkname, filename, MAX_PATH);
  215. if (linksize <= 0)
  216. return 0;
  217. filename[linksize] = 0;
  218. pid = atoi(file);
  219. if (pid >= getpid())
  220. return 0;
  221. snprintf(linkname, MAX_PATH, "%s/%s/fd", dir, file);
  222. if (!ls_dir(linkname, is_same_linkfile, argv))
  223. return 0;
  224. dbg_time("%s/%s/exe -> %s", dir, file, filename);
  225. while (kill_timeout-- && !kill(pid, 0))
  226. {
  227. kill(pid, SIGTERM);
  228. sleep(1);
  229. }
  230. if (!kill(pid, 0))
  231. {
  232. dbg_time("force kill %s/%s/exe -> %s", dir, file, filename);
  233. kill(pid, SIGKILL);
  234. sleep(1);
  235. }
  236. return 1;
  237. }
  238. static int kill_brothers(const char *qmichannel)
  239. {
  240. char myself[MAX_PATH];
  241. int filenamesize;
  242. void *argv[2] = {myself, (void *)qmichannel};
  243. filenamesize = readlink("/proc/self/exe", myself, MAX_PATH);
  244. if (filenamesize <= 0)
  245. return 0;
  246. myself[filenamesize] = 0;
  247. if (ls_dir("/proc", is_brother_process, argv))
  248. sleep(1);
  249. return 0;
  250. }
  251. static int kill_data_call_pdp(int pdp, char *self) {
  252. int pid;
  253. char *p = NULL;
  254. p = self;
  255. while (*self) {
  256. if (*self == '/')
  257. p = self+1;
  258. self++;
  259. }
  260. pid = getpid_by_pdp(pdp, p);
  261. if (pid > 0) {
  262. dbg_time("send SIGINT to process %d", pid);
  263. return kill(pid, SIGINT);
  264. }
  265. return -1;
  266. }
  267. static void ql_sigaction(int signo) {
  268. if (SIGALRM == signo)
  269. send_signo_to_main(SIG_EVENT_START);
  270. else
  271. {
  272. main_loop = 0;
  273. send_signo_to_main(SIG_EVENT_STOP);
  274. main_send_event_to_qmidevice(SIG_EVENT_STOP); //main may be wating qmi response
  275. }
  276. }
  277. pthread_t gQmiThreadID;
  278. static int usage(const char *progname) {
  279. dbg_time("Usage: %s [options]", progname);
  280. dbg_time("-s [apn [user password auth]] Set apn/user/password/auth get from your network provider");
  281. dbg_time("-p pincode Verify sim card pin if sim card is locked");
  282. dbg_time("-f logfilename Save log message of this program to file");
  283. dbg_time("-u usbmonlog filename Save usbmon log of this program to file");
  284. dbg_time("-i interface Specify network interface(default auto-detect)");
  285. dbg_time("-4 IPv4 protocol");
  286. dbg_time("-6 IPv6 protocol");
  287. dbg_time("-m muxID Specify muxid when set multi-pdn data connection.");
  288. dbg_time("-n channelID Specify channelID when set multi-pdn data connection(default 1).");
  289. dbg_time("-k channelID Send SIGINT to quectel-CM which multi-pdn is channelID.");
  290. dbg_time("-r Detach and attach kernel driver before open device.");
  291. dbg_time("-b enable network interface bridge function(default 0).");
  292. dbg_time("[Examples]");
  293. dbg_time("Example 1: %s ", progname);
  294. dbg_time("Example 2: %s -s 3gnet ", progname);
  295. dbg_time("Example 3: %s -s 3gnet carl 1234 0 -p 1234 -f gobinet_log.txt", progname);
  296. return 0;
  297. }
  298. int qmi_main(PROFILE_T *profile)
  299. {
  300. int triger_event = 0;
  301. int signo;
  302. #ifdef CONFIG_SIM
  303. SIM_Status SIMStatus;
  304. #endif
  305. UCHAR PSAttachedState;
  306. UCHAR IPv4ConnectionStatus = 0xff; //unknow state
  307. UCHAR IPv6ConnectionStatus = 0xff; //unknow state
  308. unsigned SetupCallFail = 0;
  309. unsigned long SetupCallAllowTime = clock_msec();
  310. int qmierr = 0;
  311. char * save_usbnet_adapter = NULL;
  312. /* signal trigger quit event */
  313. signal(SIGINT, ql_sigaction);
  314. signal(SIGTERM, ql_sigaction);
  315. /* timer routine */
  316. signal(SIGALRM, ql_sigaction);
  317. #ifdef CONFIG_BACKGROUND_WHEN_GET_IP
  318. ql_prepare_daemon();
  319. #endif
  320. //sudo apt-get install udhcpc
  321. //sudo apt-get remove ModemManager
  322. __main_loop:
  323. if (profile->reattach_flag) {
  324. if (!reattach_driver(profile))
  325. sleep(2);
  326. }
  327. /* try to recreate FDs*/
  328. if (socketpair( AF_LOCAL, SOCK_STREAM, 0, signal_control_fd) < 0 ) {
  329. dbg_time("%s Faild to create main_control_fd: %d (%s)", __func__, errno, strerror(errno));
  330. return -1;
  331. }
  332. if ( socketpair( AF_LOCAL, SOCK_STREAM, 0, qmidevice_control_fd ) < 0 ) {
  333. dbg_time("%s Failed to create thread control socket pair: %d (%s)", __func__, errno, strerror(errno));
  334. return 0;
  335. }
  336. while (!profile->qmichannel) {
  337. char qmichannel[32+1] = {'\0'};
  338. char usbnet_adapter[32+1] = {'\0'};
  339. if (!qmidevice_detect(qmichannel, usbnet_adapter, sizeof(qmichannel), &profile->busnum, &profile->devnum)) {
  340. dbg_time("qmidevice_detect failed");
  341. continue;
  342. } else {
  343. if (!(profile->qmichannel))
  344. strset(profile->qmichannel, qmichannel);
  345. if (!(profile->usbnet_adapter))
  346. strset(profile->usbnet_adapter, usbnet_adapter);
  347. break;
  348. }
  349. if (main_loop) {
  350. int wait_for_device = 3000;
  351. dbg_time("Wait for Quectel modules connect");
  352. while (wait_for_device && main_loop) {
  353. wait_for_device -= 100;
  354. usleep(100*1000);
  355. }
  356. continue;
  357. }
  358. dbg_time("Cannot find qmichannel(%s) usbnet_adapter(%s) for Quectel modules", profile->qmichannel, profile->usbnet_adapter);
  359. return -ENODEV;
  360. }
  361. if (qmidev_is_gobinet(profile->qmichannel)) {
  362. profile->qmi_ops = &gobi_qmidev_ops;
  363. }
  364. else {
  365. profile->qmi_ops = &qmiwwan_qmidev_ops;
  366. }
  367. qmidev_send = profile->qmi_ops->send;
  368. if (profile->qmap_mode == 0 || profile->qmap_mode == 1)
  369. kill_brothers(profile->qmichannel);
  370. if (pthread_create( &gQmiThreadID, 0, profile->qmi_ops->read, (void *)profile) != 0) {
  371. dbg_time("%s Failed to create QMIThread: %d (%s)", __func__, errno, strerror(errno));
  372. return 0;
  373. }
  374. if ((read(qmidevice_control_fd[0], &triger_event, sizeof(triger_event)) != sizeof(triger_event))
  375. || (triger_event != RIL_INDICATE_DEVICE_CONNECTED)) {
  376. dbg_time("%s Failed to init QMIThread: %d (%s)", __func__, errno, strerror(errno));
  377. return 0;
  378. }
  379. if (profile->qmi_ops->init && profile->qmi_ops->init(profile)) {
  380. dbg_time("%s Failed to qmi init: %d (%s)", __func__, errno, strerror(errno));
  381. return 0;
  382. }
  383. #ifdef CONFIG_VERSION
  384. requestBaseBandVersion(NULL);
  385. #endif
  386. requestSetEthMode(profile);
  387. if (profile->loopback_state) {
  388. requestSetLoopBackState(profile->loopback_state, profile->replication_factor);
  389. profile->loopback_state = 0;
  390. }
  391. #ifdef CONFIG_SIM
  392. qmierr = requestGetSIMStatus(&SIMStatus);
  393. while (qmierr == QMI_ERR_OP_DEVICE_UNSUPPORTED) {
  394. sleep(1);
  395. qmierr = requestGetSIMStatus(&SIMStatus);
  396. }
  397. if ((SIMStatus == SIM_PIN) && profile->pincode) {
  398. requestEnterSimPin(profile->pincode);
  399. }
  400. #ifdef CONFIG_IMSI_ICCID
  401. if (SIMStatus == SIM_READY) {
  402. requestGetICCID();
  403. requestGetIMSI();
  404. }
  405. #endif
  406. #endif
  407. #ifdef CONFIG_APN
  408. if (profile->apn || profile->user || profile->password) {
  409. requestSetProfile(profile);
  410. }
  411. requestGetProfile(profile);
  412. #endif
  413. requestRegistrationState(&PSAttachedState);
  414. send_signo_to_main(SIG_EVENT_CHECK);
  415. #ifdef CONFIG_PID_FILE_FORMAT
  416. {
  417. char cmd[255];
  418. sprintf(cmd, "echo %d > " CONFIG_PID_FILE_FORMAT, getpid(), profile->usbnet_adapter);
  419. system(cmd);
  420. }
  421. #endif
  422. while (1)
  423. {
  424. struct pollfd pollfds[] = {{signal_control_fd[1], POLLIN, 0}, {qmidevice_control_fd[0], POLLIN, 0}};
  425. int ne, ret, nevents = sizeof(pollfds)/sizeof(pollfds[0]);
  426. do {
  427. ret = poll(pollfds, nevents, 15*1000);
  428. } while ((ret < 0) && (errno == EINTR));
  429. if (ret == 0)
  430. {
  431. send_signo_to_main(SIG_EVENT_CHECK);
  432. continue;
  433. }
  434. if (ret <= 0) {
  435. dbg_time("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
  436. goto __main_quit;
  437. }
  438. for (ne = 0; ne < nevents; ne++) {
  439. int fd = pollfds[ne].fd;
  440. short revents = pollfds[ne].revents;
  441. if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
  442. dbg_time("%s poll err/hup", __func__);
  443. dbg_time("epoll fd = %d, events = 0x%04x", fd, revents);
  444. main_send_event_to_qmidevice(RIL_REQUEST_QUIT);
  445. if (revents & POLLHUP)
  446. goto __main_quit;
  447. }
  448. if ((revents & POLLIN) == 0)
  449. continue;
  450. if (fd == signal_control_fd[1])
  451. {
  452. if (read(fd, &signo, sizeof(signo)) == sizeof(signo))
  453. {
  454. alarm(0);
  455. switch (signo)
  456. {
  457. case SIG_EVENT_START:
  458. if (PSAttachedState != 1 && profile->loopback_state == 0)
  459. break;
  460. if (SetupCallAllowTime > clock_msec()) {
  461. alarm((SetupCallAllowTime - clock_msec()+999)/1000);
  462. break;
  463. }
  464. if (profile->enable_ipv4 && IPv4ConnectionStatus != QWDS_PKT_DATA_CONNECTED) {
  465. qmierr = requestSetupDataCall(profile, IpFamilyV4);
  466. if ((qmierr > 0) && profile->user && profile->user[0] && profile->password && profile->password[0]) {
  467. int old_auto = profile->auth;
  468. //may be fail because wrong auth mode, try pap->chap, or chap->pap
  469. profile->auth = (profile->auth == 1) ? 2 : 1;
  470. qmierr = requestSetupDataCall(profile, IpFamilyV4);
  471. if (qmierr)
  472. profile->auth = old_auto; //still fail, restore old auth moe
  473. }
  474. if (!qmierr) {
  475. qmierr = requestGetIPAddress(profile, IpFamilyV4);
  476. if (!qmierr)
  477. IPv4ConnectionStatus = QWDS_PKT_DATA_CONNECTED;
  478. }
  479. }
  480. if (profile->enable_ipv6 && IPv6ConnectionStatus != QWDS_PKT_DATA_CONNECTED) {
  481. qmierr = requestSetupDataCall(profile, IpFamilyV6);
  482. if (!qmierr) {
  483. qmierr = requestGetIPAddress(profile, IpFamilyV6);
  484. if (!qmierr)
  485. IPv6ConnectionStatus = QWDS_PKT_DATA_CONNECTED;
  486. }
  487. }
  488. if ((profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)
  489. || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) {
  490. const unsigned allow_time[] = {5, 10, 20, 40, 60};
  491. if (SetupCallFail < (sizeof(allow_time)/sizeof(unsigned)))
  492. SetupCallAllowTime = allow_time[SetupCallFail];
  493. else
  494. SetupCallAllowTime = 60;
  495. SetupCallFail++;
  496. dbg_time("try to requestSetupDataCall %ld second later", SetupCallAllowTime);
  497. alarm(SetupCallAllowTime);
  498. SetupCallAllowTime = SetupCallAllowTime*1000 + clock_msec();
  499. #ifdef CONFIG_EXIT_WHEN_DIAL_FAILED
  500. send_signo_to_main(SIG_EVENT_STOP);
  501. #endif
  502. }
  503. else if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) {
  504. SetupCallFail = 0;
  505. SetupCallAllowTime = clock_msec();
  506. }
  507. break;
  508. case SIG_EVENT_CHECK:
  509. #ifdef CONFIG_SIGNALINFO
  510. requestGetSignalInfo();
  511. #endif
  512. if (profile->enable_ipv4) {
  513. requestQueryDataCall(&IPv4ConnectionStatus, IpFamilyV4);
  514. //local ip is different with remote ip
  515. if (QWDS_PKT_DATA_CONNECTED == IPv4ConnectionStatus && check_ipv4_address(profile) == 0) {
  516. requestDeactivateDefaultPDP(profile, IpFamilyV4);
  517. IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
  518. }
  519. }
  520. else {
  521. IPv4ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
  522. }
  523. if (profile->enable_ipv6) {
  524. requestQueryDataCall(&IPv6ConnectionStatus, IpFamilyV6);
  525. }
  526. else {
  527. IPv6ConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
  528. }
  529. if (IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED) {
  530. usbnet_link_change(0, profile);
  531. }
  532. else if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) {
  533. usbnet_link_change(1, profile);
  534. }
  535. if ((profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)
  536. || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) {
  537. send_signo_to_main(SIG_EVENT_START);
  538. }
  539. break;
  540. case SIG_EVENT_STOP:
  541. if (profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED) {
  542. requestDeactivateDefaultPDP(profile, IpFamilyV4);
  543. }
  544. if (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED) {
  545. requestDeactivateDefaultPDP(profile, IpFamilyV6);
  546. }
  547. usbnet_link_change(0, profile);
  548. if (profile->qmi_ops->deinit)
  549. profile->qmi_ops->deinit();
  550. main_send_event_to_qmidevice(RIL_REQUEST_QUIT);
  551. goto __main_quit;
  552. break;
  553. default:
  554. break;
  555. }
  556. }
  557. }
  558. if (fd == qmidevice_control_fd[0]) {
  559. if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) {
  560. switch (triger_event) {
  561. case RIL_INDICATE_DEVICE_DISCONNECTED:
  562. usbnet_link_change(0, profile);
  563. if (main_loop)
  564. {
  565. if (pthread_join(gQmiThreadID, NULL)) {
  566. dbg_time("%s Error joining to listener thread (%s)", __func__, strerror(errno));
  567. }
  568. profile->qmichannel = NULL;
  569. profile->usbnet_adapter = save_usbnet_adapter;
  570. goto __main_loop;
  571. }
  572. goto __main_quit;
  573. break;
  574. case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:
  575. requestRegistrationState(&PSAttachedState);
  576. if (PSAttachedState == 1) {
  577. if ((profile->enable_ipv4 && IPv4ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)
  578. || (profile->enable_ipv6 && IPv6ConnectionStatus == QWDS_PKT_DATA_DISCONNECTED)) {
  579. send_signo_to_main(SIG_EVENT_START);
  580. }
  581. } else {
  582. SetupCallAllowTime = clock_msec();
  583. }
  584. break;
  585. case RIL_UNSOL_DATA_CALL_LIST_CHANGED:
  586. if (IPv4ConnectionStatus == QWDS_PKT_DATA_CONNECTED || IPv6ConnectionStatus == QWDS_PKT_DATA_CONNECTED)
  587. SetupCallAllowTime = clock_msec() + 1000; //from connect -> disconnect, do not re-dail immediately, wait network stable
  588. send_signo_to_main(SIG_EVENT_CHECK);
  589. break;
  590. case MODEM_REPORT_RESET_EVENT:
  591. {
  592. unsigned int time_to_wait = 20;
  593. unsigned int time_expired = 0;
  594. dbg_time("main recv MODEM RESET SIGNAL");
  595. dbg_time("quit QMI thread and wait %ds and try to restart", time_to_wait);
  596. main_send_event_to_qmidevice(RIL_REQUEST_QUIT);
  597. /** NOTICE
  598. * DO NOT CALL usbnet_link_change(0, profile) DIRECTLLY
  599. * for, the modem may go into wrong state(only ttyUSB0 left) and wont go back
  600. */
  601. usbnet_link_state(0);
  602. /* close FDs, for we want restart. */
  603. close(signal_control_fd[0]);
  604. close(signal_control_fd[1]);
  605. close(qmidevice_control_fd[0]);
  606. close(qmidevice_control_fd[1]);
  607. while (time_expired++ < time_to_wait) {
  608. sleep(1);
  609. char qmidev[64] = {'\0'};
  610. snprintf(qmidev, sizeof(qmidev), "/dev/bus/usb/%03d/%03d", profile->busnum, profile->devnum);
  611. if (access(qmidev, F_OK)) {
  612. dbg_time("whoo, fatal error info, qmi device node disappeared!!! cannot continue!\n");
  613. goto __main_quit;
  614. }
  615. }
  616. dbg_time("main try do restart");
  617. goto __main_loop;
  618. }
  619. case RIL_UNSOL_LOOPBACK_CONFIG_IND:
  620. {
  621. QMI_WDA_SET_LOOPBACK_CONFIG_IND_MSG SetLoopBackInd;
  622. if (read(fd, &SetLoopBackInd, sizeof(SetLoopBackInd)) == sizeof(SetLoopBackInd)) {
  623. profile->loopback_state = SetLoopBackInd.loopback_state.TLVVaule;
  624. profile->replication_factor = le32_to_cpu(SetLoopBackInd.replication_factor.TLVVaule);
  625. dbg_time("SetLoopBackInd: loopback_state=%d, replication_factor=%u",
  626. profile->loopback_state, profile->replication_factor);
  627. if (profile->loopback_state)
  628. send_signo_to_main(SIG_EVENT_START);
  629. }
  630. }
  631. break;
  632. default:
  633. break;
  634. }
  635. }
  636. }
  637. }
  638. }
  639. __main_quit:
  640. usbnet_link_change(0, profile);
  641. if (pthread_join(gQmiThreadID, NULL)) {
  642. dbg_time("%s Error joining to listener thread (%s)", __func__, strerror(errno));
  643. }
  644. close(signal_control_fd[0]);
  645. close(signal_control_fd[1]);
  646. close(qmidevice_control_fd[0]);
  647. close(qmidevice_control_fd[1]);
  648. dbg_time("%s exit", __func__);
  649. #ifdef CONFIG_PID_FILE_FORMAT
  650. {
  651. char cmd[255];
  652. sprintf(cmd, "rm " CONFIG_PID_FILE_FORMAT, profile.usbnet_adapter);
  653. system(cmd);
  654. }
  655. #endif
  656. return 0;
  657. }
  658. #define has_more_argv() ((opt < argc) && (argv[opt][0] != '-'))
  659. int main(int argc, char *argv[])
  660. {
  661. int opt = 1;
  662. char * save_usbnet_adapter = NULL;
  663. const char *usbmon_logfile = NULL;
  664. PROFILE_T profile;
  665. int ret = -1;
  666. dbg_time("Quectel_QConnectManager_Linux_V1.6.0.16:Iflytop V1.0");
  667. memset(&profile, 0x00, sizeof(profile));
  668. profile.pdp = CONFIG_DEFAULT_PDP;
  669. if (!strcmp(argv[argc-1], "&"))
  670. argc--;
  671. opt = 1;
  672. while (opt < argc) {
  673. if (argv[opt][0] != '-')
  674. return usage(argv[0]);
  675. switch (argv[opt++][1])
  676. {
  677. case 's':
  678. profile.apn = profile.user = profile.password = "";
  679. if (has_more_argv())
  680. profile.apn = argv[opt++];
  681. if (has_more_argv())
  682. profile.user = argv[opt++];
  683. if (has_more_argv())
  684. {
  685. profile.password = argv[opt++];
  686. if (profile.password && profile.password[0])
  687. profile.auth = 2; //default chap, customers may miss auth
  688. }
  689. if (has_more_argv())
  690. profile.auth = argv[opt++][0] - '0';
  691. break;
  692. case 'm':
  693. if (has_more_argv())
  694. profile.muxid = argv[opt++][0] - '0';
  695. break;
  696. case 'p':
  697. if (has_more_argv())
  698. profile.pincode = argv[opt++];
  699. break;
  700. case 'n':
  701. if (has_more_argv())
  702. profile.pdp = argv[opt++][0] - '0';
  703. break;
  704. case 'f':
  705. if (has_more_argv())
  706. {
  707. const char * filename = argv[opt++];
  708. logfilefp = fopen(filename, "a+");
  709. if (!logfilefp) {
  710. dbg_time("Fail to open %s, errno: %d(%s)", filename, errno, strerror(errno));
  711. }
  712. }
  713. break;
  714. case 'i':
  715. if (has_more_argv())
  716. profile.usbnet_adapter = save_usbnet_adapter = argv[opt++];
  717. break;
  718. case 'v':
  719. debug_qmi = 1;
  720. break;
  721. case 'l':
  722. if (has_more_argv()) {
  723. profile.replication_factor = atoi(argv[opt++]);
  724. if (profile.replication_factor > 0)
  725. profile.loopback_state = 1;
  726. }
  727. else
  728. main_loop = 1;
  729. break;
  730. case '4':
  731. profile.enable_ipv4 = 1;
  732. break;
  733. case '6':
  734. profile.enable_ipv6 = 1;
  735. break;
  736. case 'd':
  737. if (has_more_argv()) {
  738. profile.qmichannel = argv[opt++];
  739. if (qmidev_is_pciemhi(profile.qmichannel))
  740. profile.usbnet_adapter = "pcie_mhi0";
  741. }
  742. break;
  743. case 'r':
  744. profile.reattach_flag = 1;
  745. break;
  746. case 'u':
  747. if (has_more_argv()) {
  748. usbmon_logfile = argv[opt++];
  749. }
  750. break;
  751. case 'b':
  752. profile.enable_bridge = 1;
  753. break;
  754. case 'k':
  755. if (has_more_argv()) {
  756. return kill_data_call_pdp(argv[opt++][0] - '0', argv[0]);
  757. }
  758. default:
  759. return usage(argv[0]);
  760. break;
  761. }
  762. }
  763. if (profile.enable_ipv4 != 1 && profile.enable_ipv6 != 1) { // default enable IPv4
  764. profile.enable_ipv4 = 1;
  765. }
  766. if (!(profile.qmichannel) || !(profile.usbnet_adapter)) {
  767. char qmichannel[32+1] = {'\0'};
  768. char usbnet_adapter[32+1] = {'\0'};
  769. if (profile.usbnet_adapter)
  770. strcpy(usbnet_adapter, profile.usbnet_adapter);
  771. if (qmidevice_detect(qmichannel, usbnet_adapter, sizeof(qmichannel), &profile.busnum, &profile.devnum)) {
  772. profile.hardware_interface = HARDWARE_USB;
  773. }
  774. else if (mhidevice_detect(qmichannel, usbnet_adapter, &profile)) {
  775. profile.hardware_interface = HARDWARE_PCIE;
  776. }
  777. else {
  778. dbg_time("qmidevice_detect failed");
  779. goto error;
  780. }
  781. if (!(profile.qmichannel))
  782. strset(profile.qmichannel, qmichannel);
  783. if (!(profile.usbnet_adapter))
  784. strset(profile.usbnet_adapter, usbnet_adapter);
  785. ql_get_netcard_driver_info(profile.usbnet_adapter);
  786. if ((profile.hardware_interface == HARDWARE_USB) && usbmon_logfile)
  787. ql_capture_usbmon_log(&profile, usbmon_logfile);
  788. if (profile.hardware_interface == HARDWARE_USB) {
  789. profile.software_interface = get_driver_type(&profile);
  790. }
  791. }
  792. ql_qmap_mode_detect(&profile);
  793. if (profile.software_interface == SOFTWARE_MBIM) {
  794. dbg_time("Modem works in MBIM mode");
  795. ret = mbim_main(&profile);
  796. } else if (profile.software_interface == SOFTWARE_QMI) {
  797. dbg_time("Modem works in QMI mode");
  798. ret = qmi_main(&profile);
  799. }
  800. ql_stop_usbmon_log(&profile);
  801. if (logfilefp)
  802. fclose(logfilefp);
  803. error:
  804. return ret;
  805. }