ppp_device.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619
  1. /*
  2. * Copyright (c) 2006-2019, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-15 xiangxistu the first version
  9. * 2019-10-01 xiaofan rewrite ppp_recv thread
  10. * 2022-01-16 Jianjia Ma implement timeout for continuous data
  11. */
  12. #include <ppp_device.h>
  13. #include <ppp_netif.h>
  14. #define DBG_TAG "ppp.dev"
  15. #ifdef PPP_DEVICE_DEBUG
  16. #define DBG_LVL DBG_LOG
  17. #else
  18. #define DBG_LVL DBG_INFO
  19. #endif
  20. #include <rtdbg.h>
  21. #ifdef PPP_DEVICE_DEBUG
  22. #define PPP_THREAD_STACK_SIZE 2048
  23. #else
  24. #define PPP_THREAD_STACK_SIZE 1280
  25. #endif
  26. #define PPP_THREAD_PRIORITY 9
  27. enum
  28. {
  29. PPP_STATE_PREPARE,
  30. PPP_STATE_RECV_DATA,
  31. };
  32. #define PPP_RECV_READ_MAX 128
  33. #define PPP_EVENT_RX_NOTIFY 1 // serial incoming a byte
  34. #define PPP_EVENT_LOST 2 // PPP connection is lost
  35. #define PPP_EVENT_CLOSE_REQ 4 // user want close ppp_device
  36. #define PPP_EVENT_CLOSED 8 // ppp_recv thread will send CLOSED event when ppp_recv thread is safe exit
  37. #if RT_LWIP_TCPTHREAD_STACKSIZE < 2048
  38. #error "tcpip stack is too small, should greater than 2048."
  39. #endif
  40. static struct ppp_device *_g_ppp_device = RT_NULL;
  41. /**
  42. * dump ppp data according to hex format,you can see data what you recieve , send, and ppp_device dorp out
  43. *
  44. * @param data the data what you want to dump out
  45. * @param len the length of those data
  46. */
  47. #ifdef PPP_DEVICE_DEBUG
  48. static void ppp_debug_hexdump(const void *data, size_t len)
  49. {
  50. rt_uint16_t maxlen = 16;
  51. rt_uint32_t offset = 0;
  52. size_t curlen = 0, i = 0;
  53. char line[16 * 4 + 3] = {0};
  54. char *p = RT_NULL;
  55. const unsigned char *src = data;
  56. while (len > 0)
  57. {
  58. curlen = len < maxlen ? len : maxlen;
  59. p = line;
  60. for (i = 0; i < curlen; i++)
  61. {
  62. rt_sprintf(p, "%02x ", (unsigned char)src[i]);
  63. p += 3;
  64. }
  65. memset(p, ' ', (maxlen - curlen) * 3);
  66. p += (maxlen - curlen) * 3;
  67. *p++ = '|';
  68. *p++ = ' ';
  69. for (i = 0; i < curlen; i++)
  70. {
  71. *p++ = (0x20 < src[i] && src[i] < 0x7e) ? src[i] : '.';
  72. }
  73. *p++ = '\0';
  74. LOG_D("[%04x] %s", offset, line);
  75. len -= curlen;
  76. src += curlen;
  77. offset += curlen;
  78. }
  79. }
  80. #endif
  81. /**
  82. * Receive callback function , send PPP_EVENT_RX_NOTIFY event when uart acquire data
  83. *
  84. * @param dev the point of device driver structure, uart structure
  85. * @param size the indication callback function need this parameter
  86. *
  87. * @return RT_EOK
  88. */
  89. static rt_err_t ppp_device_rx_ind(rt_device_t dev, rt_size_t size)
  90. {
  91. RT_ASSERT(dev != RT_NULL);
  92. struct ppp_device *ppp_dev = _g_ppp_device;
  93. /* when recieve data from uart , send event to wake up recieve thread */
  94. rt_event_send(&ppp_dev->event, PPP_EVENT_RX_NOTIFY);
  95. return RT_EOK;
  96. }
  97. /**
  98. * using ppp_data_send send data to lwIP procotol stack PPPoS serial output callback
  99. *
  100. * @param pcb pcb PPP control block
  101. * @param data data Buffer to write to serial port
  102. * @param len the Length of the data buffer
  103. * @param ppp_device ctx Context of callback , ppp_device
  104. *
  105. * @return the point of rt_device_write fucntion or RT_NULL
  106. */
  107. static uint32_t ppp_data_send(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *ppp_device)
  108. {
  109. RT_ASSERT(pcb != RT_NULL);
  110. RT_ASSERT(ppp_device != RT_NULL);
  111. struct ppp_device *device = (struct ppp_device *)ppp_device;
  112. if (device->state == PPP_STATE_PREPARE)
  113. return 0;
  114. #ifdef PPP_DEVICE_DEBUG_TX
  115. LOG_D("TX:");
  116. ppp_debug_hexdump(data, len);
  117. #endif
  118. /* the return data is the actually written size on successful */
  119. return rt_device_write(device->uart, 0, data, len);
  120. }
  121. /**
  122. * ppp_status_changed callback function
  123. *
  124. * @param pcb protocol caontrol block
  125. * @param err_code the result of ppp conncet
  126. * @param ctx ctx Context of callback , ppp_device
  127. */
  128. static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
  129. {
  130. struct ppp_device *pppdev = (struct ppp_device *)ctx;
  131. struct netif *pppif = ppp_netif(pcb);
  132. switch (err_code)
  133. {
  134. case PPPERR_NONE: /* Connected */
  135. pppdev->pppif.mtu = pppif->mtu;
  136. ppp_netdev_refresh(&pppdev->pppif);
  137. LOG_I("ppp_device connect successfully.");
  138. break;
  139. case PPPERR_PARAM:
  140. LOG_E("Invalid parameter.");
  141. break;
  142. case PPPERR_OPEN:
  143. LOG_E("Unable to open PPP session.");
  144. break;
  145. case PPPERR_DEVICE:
  146. LOG_E("Invalid I/O device for PPP.");
  147. break;
  148. case PPPERR_ALLOC:
  149. LOG_E("Unable to allocate resources.");
  150. break;
  151. case PPPERR_USER:
  152. LOG_D("User interrupt");
  153. break;
  154. case PPPERR_CONNECT: /* Connection lost */
  155. LOG_E("ppp connect lost.");
  156. break;
  157. case PPPERR_AUTHFAIL:
  158. LOG_E("Failed authentication challenge.");
  159. break;
  160. case PPPERR_PROTOCOL:
  161. LOG_E("Failed to meet protocol.");
  162. break;
  163. case PPPERR_PEERDEAD:
  164. LOG_E("Connection timeout.");
  165. break;
  166. case PPPERR_IDLETIMEOUT:
  167. LOG_E("Idle Timeout.");
  168. break;
  169. case PPPERR_CONNECTTIME:
  170. LOG_E("Max connect time reached.");
  171. break;
  172. case PPPERR_LOOPBACK:
  173. LOG_E("Loopback detected.");
  174. break;
  175. default:
  176. LOG_E("Unknown error code %d.", err_code);
  177. break;
  178. }
  179. if (err_code != PPPERR_NONE)
  180. rt_event_send(&pppdev->event, PPP_EVENT_LOST);
  181. }
  182. /**
  183. * Receive thread , store uart data and transform tcpip stack
  184. *
  185. * @param device the point of device driver structure, ppp_device structure
  186. *
  187. * @return RT_EOK we shouldn't let the recieve thread return data, recieve thread need keepalive all the time
  188. */
  189. static int ppp_recv_entry(struct ppp_device *device)
  190. {
  191. const rt_uint32_t interested_event = PPP_EVENT_RX_NOTIFY | PPP_EVENT_LOST | PPP_EVENT_CLOSE_REQ;
  192. rt_uint32_t event;
  193. rt_tick_t last_recv_tick;
  194. rt_size_t rlen;
  195. rt_size_t len;
  196. rt_uint8_t buffer[PPP_RECV_READ_MAX];
  197. rt_bool_t closing = RT_FALSE;
  198. rt_event_control(&device->event, RT_IPC_CMD_RESET, RT_NULL);
  199. device->state = PPP_STATE_PREPARE;
  200. while (1)
  201. {
  202. if (device->state == PPP_STATE_PREPARE)
  203. {
  204. if (!device->ops->prepare || device->ops->prepare(device) == RT_EOK)
  205. {
  206. /* throw away the dirty data in the uart buffer */
  207. rt_device_read(device->uart, 0, buffer, PPP_RECV_READ_MAX);
  208. device->state = PPP_STATE_RECV_DATA;
  209. pppapi_connect(device->pcb, 0);
  210. }
  211. else
  212. {
  213. LOG_E("%s prepare fail, try again later", device->parent.parent.name);
  214. rt_thread_mdelay(10*1000);
  215. }
  216. continue;
  217. }
  218. rt_event_recv(&device->event, interested_event, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
  219. if (event & PPP_EVENT_RX_NOTIFY)
  220. {
  221. len = 0;
  222. rlen = 0;
  223. last_recv_tick = rt_tick_get_millisecond();
  224. do
  225. {
  226. rlen = rt_device_read(device->uart, 0, &buffer[len], PPP_RECV_READ_MAX - len);
  227. len += rlen;
  228. if(rlen)
  229. {
  230. last_recv_tick = rt_tick_get_millisecond();
  231. }
  232. /* wait until buffer full or no more data receiving for 1ms */
  233. if (len >= PPP_RECV_READ_MAX || rt_tick_get_millisecond() - last_recv_tick >= 1)
  234. {
  235. pppos_input_tcpip(device->pcb, (u8_t *)buffer, len);
  236. len = 0;
  237. }
  238. #ifdef PPP_DEVICE_DEBUG_RX
  239. LOG_D("RX:");
  240. ppp_debug_hexdump(buffer, len);
  241. #else
  242. /* slow down the speed of receive, transfer more data to ppp in once. */
  243. rt_thread_mdelay(1);
  244. #endif
  245. } while (len);
  246. }
  247. if (event & PPP_EVENT_CLOSE_REQ)
  248. {
  249. LOG_D("user request close ppp");
  250. closing = RT_TRUE;
  251. pppapi_close(device->pcb, 0);
  252. }
  253. if (event & PPP_EVENT_LOST)
  254. {
  255. if (closing)
  256. {
  257. LOG_W("ppp closing success");
  258. rt_event_send(&device->event, PPP_EVENT_CLOSED);
  259. break;
  260. }
  261. LOG_W("ppp lost, try reconnect");
  262. device->state = PPP_STATE_PREPARE;
  263. }
  264. }
  265. return RT_EOK;
  266. }
  267. /**
  268. * Creat a thread to creat receive thread function
  269. *
  270. * @param device the point of device driver structure, ppp_device structure
  271. *
  272. * @return RT_EOK recieve thread create and startup successfully
  273. * -RT_ERROR create recieve thread successfully
  274. * -RT_ENOMEM startup recieve thread successfully
  275. */
  276. static int ppp_recv_entry_creat(struct ppp_device *device)
  277. {
  278. rt_int8_t result = RT_EOK;
  279. /* dynamic creat a recv_thread */
  280. device->recv_tid = rt_thread_create("ppp_recv",
  281. (void (*)(void *parameter))ppp_recv_entry,
  282. device,
  283. PPP_THREAD_STACK_SIZE,
  284. PPP_THREAD_PRIORITY,
  285. 20);
  286. if (device->recv_tid == RT_NULL)
  287. {
  288. LOG_E("PPP device initialize failed! ppp_device_recv_tid create failed!");
  289. result = -RT_ENOMEM;
  290. goto __exit;
  291. }
  292. /* if you create a thread, never forget to start it */
  293. result = rt_thread_startup(device->recv_tid);
  294. if(result != RT_EOK)
  295. goto __exit;
  296. return result;
  297. __exit:
  298. rt_memset(device, 0x00, sizeof(struct ppp_device));
  299. return result;
  300. }
  301. /**
  302. * ppp device init function,set ops funciton and base config
  303. *
  304. * @param device the point of device driver structure, rt_device structure
  305. *
  306. * @return RT_EOK
  307. */
  308. static rt_err_t ppp_device_init(struct rt_device *device)
  309. {
  310. RT_ASSERT(device != RT_NULL);
  311. struct ppp_device *ppp_device = (struct ppp_device *)device;
  312. RT_ASSERT(ppp_device != RT_NULL);
  313. device->flag |= RT_DEVICE_FLAG_STANDALONE;
  314. #ifdef PPP_DEVICE_DEBUG_DROP
  315. ppp_device->dropcnt = 0;
  316. ppp_device->droppos = 0;
  317. #endif
  318. return RT_EOK;
  319. }
  320. /**
  321. * initialize ppp device and set callback function
  322. *
  323. * @param device the point of device driver structure, rt_device structure
  324. * @param oflag the open flag of rt_device
  325. *
  326. * @return the result
  327. */
  328. static rt_err_t ppp_device_open(struct rt_device *device, rt_uint16_t oflag)
  329. {
  330. int result = RT_EOK;
  331. rt_uint16_t uart_oflag;
  332. RT_ASSERT(device != RT_NULL);
  333. struct ppp_device *ppp_device = (struct ppp_device *)device;
  334. uart_oflag = RT_DEVICE_OFLAG_RDWR;
  335. if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_RX)
  336. uart_oflag |= RT_DEVICE_FLAG_DMA_RX;
  337. else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_RX)
  338. uart_oflag = RT_DEVICE_FLAG_INT_RX;
  339. if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_TX)
  340. uart_oflag |= RT_DEVICE_FLAG_DMA_TX;
  341. else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_TX)
  342. uart_oflag |= RT_DEVICE_FLAG_INT_TX;
  343. if (rt_device_open(ppp_device->uart, uart_oflag) != RT_EOK)
  344. {
  345. LOG_E("ppp device open failed.");
  346. result = -RT_ERROR;
  347. goto __exit;
  348. }
  349. rt_event_init(&ppp_device->event, "pppev", RT_IPC_FLAG_FIFO);
  350. /* we can do nothing */
  351. RT_ASSERT(ppp_device->uart && ppp_device->uart->type == RT_Device_Class_Char);
  352. /* uart transfer into tcpip protocol stack */
  353. rt_device_set_rx_indicate(ppp_device->uart, ppp_device_rx_ind);
  354. LOG_D("(%s) is used by ppp_device.", ppp_device->uart->parent.name);
  355. /* creat pppos */
  356. ppp_device->pcb = pppapi_pppos_create(&(ppp_device->pppif), ppp_data_send, ppp_status_changed, ppp_device);
  357. if (ppp_device->pcb == RT_NULL)
  358. {
  359. LOG_E("Create ppp pcb failed.");
  360. result = -RT_ERROR;
  361. goto __exit;
  362. }
  363. LOG_D("pppapi_pppos_create has created a protocol control block.");
  364. ppp_netdev_add(&ppp_device->pppif);
  365. /* set netif name */
  366. ppp_device->pppif.name[0] = ppp_device->parent.parent.name[0];
  367. ppp_device->pppif.name[1] = ppp_device->parent.parent.name[1];
  368. /* set default route */
  369. result = pppapi_set_default(ppp_device->pcb);
  370. if (result != RT_EOK)
  371. {
  372. LOG_E("pppapi_set_default execute failed.");
  373. result = -RT_ERROR;
  374. goto __exit;
  375. }
  376. LOG_D("pppapi_set_default has set a default route.");
  377. /* dns */
  378. ppp_set_usepeerdns(ppp_device->pcb, 1);
  379. LOG_D("ppp_set_usepeerdns has set a dns number.");
  380. #ifdef PPP_USING_PRIVATE_APN
  381. /* set authorize */
  382. #if PAP_SUPPORT
  383. ppp_set_auth(ppp_device->pcb , PPPAUTHTYPE_PAP, PPP_PRIVATE_APN_ACCOUNT, PPP_PRIVATE_APN_PASSWORD);
  384. #elif CHAP_SUPPORT
  385. ppp_set_auth(ppp_device->pcb, PPPAUTHTYPE_CHAP, ppp_device->config.user_name, ppp_device->config.user_name);
  386. #else
  387. #error "Unsupported AUTH Negotiation"
  388. #endif
  389. LOG_D("ppp_set_auth has passed verification.");
  390. #endif /* PPP_AUTHORIZE */
  391. /* Creat a thread to creat ppp recieve function */
  392. result = ppp_recv_entry_creat(ppp_device);
  393. if (result != RT_EOK)
  394. {
  395. LOG_E("Creat a thread to creat ppp recieve function failed.");
  396. result = -RT_ERROR;
  397. goto __exit;
  398. }
  399. LOG_D("Creat a thread to creat ppp recieve function successful.");
  400. __exit:
  401. return result;
  402. }
  403. /**
  404. * Close ppp device
  405. *
  406. * @param device the point of device driver structure, rt_device structure
  407. *
  408. * @return RT_EOK
  409. */
  410. static rt_err_t ppp_device_close(struct rt_device *device)
  411. {
  412. rt_uint32_t event;
  413. RT_ASSERT(device != RT_NULL);
  414. extern void ppp_netdev_del(struct netif *ppp_netif);
  415. struct ppp_device *ppp_device = (struct ppp_device *)device;
  416. RT_ASSERT(ppp_device != RT_NULL);
  417. rt_event_send(&ppp_device->event, PPP_EVENT_CLOSE_REQ);
  418. rt_event_recv(&ppp_device->event, PPP_EVENT_CLOSED, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
  419. rt_device_set_rx_indicate(ppp_device->uart, RT_NULL);
  420. ppp_netdev_del(&ppp_device->pppif);
  421. ppp_free(ppp_device->pcb);
  422. LOG_D("ppp netdev has been detach.");
  423. rt_event_detach(&ppp_device->event);
  424. rt_device_close(ppp_device->uart);
  425. /* cut down piont to piont at data link layer */
  426. LOG_I("ppp_device has been closed.");
  427. return RT_EOK;
  428. }
  429. /**
  430. * Control ppp device , access ppp mode or accsee AT mode; but not it is useless
  431. *
  432. * @param device the point of device driver structure, rt_device structure
  433. * @param cmd the command of device
  434. * @param args the private data of you send
  435. *
  436. * @return -RT_ENOSYS
  437. */
  438. static rt_err_t ppp_device_control(struct rt_device *device,int cmd, void *args)
  439. {
  440. RT_ASSERT(device != RT_NULL);
  441. return -RT_ENOSYS;
  442. }
  443. /* ppp device ops */
  444. #ifdef RT_USING_DEVICE_OPS
  445. const struct rt_device_ops ppp_device_ops =
  446. {
  447. ppp_device_init,
  448. ppp_device_open,
  449. ppp_device_close,
  450. ppp_device_control
  451. };
  452. #endif
  453. /**
  454. * Register ppp_device into rt_device frame,set ops function to rt_device inferface
  455. *
  456. * @param ppp_device the point of device driver structure, ppp_device structure
  457. * @param dev_name the name of ppp_device name
  458. * @param uart_name the name of uart name what you used
  459. * @param user_data private data
  460. *
  461. * @return RT_EOK ppp_device registered into rt_device frame successfully
  462. */
  463. int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, const char *uart_name, void *user_data)
  464. {
  465. RT_ASSERT(ppp_device != RT_NULL);
  466. rt_err_t result = RT_EOK;
  467. struct rt_device *device = RT_NULL;
  468. device = &(ppp_device->parent);
  469. device->type = RT_Device_Class_NetIf;
  470. #ifdef RT_USING_DEVICE_OPS
  471. device->ops = &ppp_device_ops;
  472. #else
  473. device->init = ppp_device_init;
  474. device->open = ppp_device_open;
  475. device->close = ppp_device_close;
  476. device->read = RT_NULL;
  477. device->write = RT_NULL;
  478. device->control = ppp_device_control;
  479. #endif
  480. /* now we supprot only one device */
  481. if (_g_ppp_device != RT_NULL)
  482. {
  483. LOG_E("Only one device support.");
  484. RT_ASSERT(_g_ppp_device == RT_NULL);
  485. }
  486. /* attention: you can't use ppp_device as a server in you network, unless
  487. sim of the modem module used supprots getting public IP address. */
  488. /* register ppp device into rt_device frame */
  489. result = rt_device_register(&ppp_device->parent, dev_name, RT_DEVICE_OFLAG_RDWR);
  490. if( result == RT_EOK)
  491. {
  492. _g_ppp_device = ppp_device;
  493. LOG_I("ppp_device(%s) register successfully.", PPP_DEVICE_NAME);
  494. }
  495. return result;
  496. }
  497. /**
  498. * attach data interface device into ppp device frame
  499. *
  500. * @param ppp_device the point of device driver structure, ppp_device structure
  501. * @param uart_name the name of uart name what you used
  502. * @param user_data private data
  503. *
  504. * @return RT_EOK execute successful
  505. * @return -RT_ERROR error
  506. */
  507. int ppp_device_attach(struct ppp_device *ppp_device, const char *uart_name, void *user_data)
  508. {
  509. RT_ASSERT(ppp_device != RT_NULL);
  510. ppp_device->uart = rt_device_find(uart_name);
  511. if (!ppp_device->uart)
  512. {
  513. LOG_E("ppp_device_attach, cannot found %s", uart_name);
  514. return -RT_ERROR;
  515. }
  516. ppp_device->user_data = user_data;
  517. if (rt_device_open(&ppp_device->parent, 0) != RT_EOK)
  518. {
  519. LOG_E("ppp_device_attach failed. Can't open device(%d)");
  520. return -RT_ERROR;
  521. }
  522. return RT_EOK;
  523. }
  524. /**
  525. * detach data interface device from ppp device frame
  526. *
  527. * @param ppp_device the point of device driver structure, ppp_device structure
  528. *
  529. * @return RT_EOK execute successful
  530. * @return -RT_ERROR error
  531. */
  532. int ppp_device_detach(struct ppp_device *ppp_device)
  533. {
  534. RT_ASSERT(ppp_device != RT_NULL);
  535. if (rt_device_close(&ppp_device->parent) != RT_EOK)
  536. {
  537. LOG_E("ppp_device_detach failed. Can't open device.");
  538. return -RT_ERROR;
  539. }
  540. ppp_device->uart = RT_NULL;
  541. ppp_device->user_data = RT_NULL;
  542. return RT_EOK;
  543. }