ppp_device.c 17 KB

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