ppp_device.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  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. */
  11. #include <ppp_device.h>
  12. #include <ppp_netif.h>
  13. #define DBG_TAG "ppp.dev"
  14. #ifdef PPP_DEVICE_DEBUG
  15. #define DBG_LVL DBG_LOG
  16. #else
  17. #define DBG_LVL DBG_INFO
  18. #endif
  19. #include <rtdbg.h>
  20. enum
  21. {
  22. PPP_STATE_PREPARE,
  23. PPP_STATE_WAIT_HEAD,
  24. PPP_STATE_RECV_DATA,
  25. };
  26. #define PPP_DATA_BEGIN_END 0x7e
  27. #define DATA_EFFECTIVE_FLAG 0x00
  28. #define RECON_ERR_COUNTS 0x02
  29. #define PPP_RECONNECT_TIME 2500
  30. #define PPP_RECV_READ_MAX 32
  31. #define PPP_EVENT_RX_NOTIFY 1 // serial incoming a byte
  32. #define PPP_EVENT_LOST 2 // PPP connection is lost
  33. #define PPP_EVENT_CLOSE_REQ 4 // user want close ppp_device
  34. #define PPP_EVENT_CLOSED 8 // ppp_recv thread will send CLOSED event when ppp_recv thread is safe exit
  35. #if RT_LWIP_TCPTHREAD_STACKSIZE < 2048
  36. #error "tcpip stack is too small, should greater than 2048."
  37. #endif
  38. static struct ppp_device *_g_ppp_device = RT_NULL;
  39. /*
  40. * dump ppp data according to hex format,you can see data what you recieve , send, and ppp_device dorp out
  41. *
  42. * @param const void *data
  43. * size_t len
  44. *
  45. * @return NULL
  46. *
  47. */
  48. #ifdef PPP_DEVICE_DEBUG
  49. static void ppp_debug_hexdump(const void *data, size_t len)
  50. {
  51. const size_t maxlen = 16;
  52. rt_uint32_t offset = 0;
  53. size_t curlen = 0, i = 0;
  54. char line[maxlen * 4 + 3] = {0};
  55. char *p = RT_NULL;
  56. const unsigned char *src = data;
  57. while (len > 0)
  58. {
  59. curlen = len < maxlen ? len : maxlen;
  60. p = line;
  61. for (i = 0; i < curlen; i++)
  62. {
  63. rt_sprintf(p, "%02x ", (unsigned char)src[i]);
  64. p += 3;
  65. }
  66. memset(p, ' ', (maxlen - curlen) * 3);
  67. p += (maxlen - curlen) * 3;
  68. *p++ = '|';
  69. *p++ = ' ';
  70. for (i = 0; i < curlen; i++)
  71. {
  72. *p++ = (0x20 < src[i] && src[i] < 0x7e) ? src[i] : '.';
  73. }
  74. *p++ = '\0';
  75. LOG_D("[%04x] %s", offset, line);
  76. len -= curlen;
  77. src += curlen;
  78. offset += curlen;
  79. }
  80. }
  81. #endif
  82. /*
  83. * Receive callback function , release rx_notice when uart acquire data
  84. *
  85. * @param rt_device_t
  86. * rt_size_t
  87. *
  88. * @return 0: execute successful
  89. *
  90. */
  91. static rt_err_t ppp_device_rx_ind(rt_device_t dev, rt_size_t size)
  92. {
  93. RT_ASSERT(dev != RT_NULL);
  94. struct ppp_device *ppp_dev = _g_ppp_device;
  95. /* when recieve data from uart , send event to wake up recieve thread */
  96. rt_event_send(&ppp_dev->event, PPP_EVENT_RX_NOTIFY);
  97. return RT_EOK;
  98. }
  99. /*
  100. * using ppp_data_send send data to lwIP procotol stack PPPoS serial output callback
  101. *
  102. * @param ppp_pcb *pcb pcb PPP control block
  103. * uint8_t *data data Buffer to write to serial port
  104. * uint32_t len len Length of the data buffer
  105. * void *ppp_device ctx Context of callback , ppp_device
  106. *
  107. * @return 0: creat response fail
  108. *
  109. */
  110. static uint32_t ppp_data_send(ppp_pcb *pcb, uint8_t *data, uint32_t len, void *ppp_device)
  111. {
  112. RT_ASSERT(pcb != RT_NULL);
  113. RT_ASSERT(ppp_device != RT_NULL);
  114. struct ppp_device *device = (struct ppp_device *)ppp_device;
  115. if (device->state == PPP_STATE_PREPARE)
  116. return 0;
  117. #ifdef PPP_DEVICE_DEBUG_TX
  118. LOG_D("TX:");
  119. ppp_debug_hexdump(data, len);
  120. #endif
  121. /* the return data is the actually written size on successful */
  122. return rt_device_write(device->uart, 0, data, len);
  123. }
  124. /*
  125. * ppp_status_changed callback function
  126. *
  127. * @param ppp_pcb *pcb protocol caontrol block
  128. * int err_code
  129. * void *ctx reserver
  130. *
  131. * @return 0: creat response fail
  132. *
  133. */
  134. static void ppp_status_changed(ppp_pcb *pcb, int err_code, void *ctx)
  135. {
  136. struct ppp_device *pppdev = (struct ppp_device *)ctx;
  137. struct netif *pppif = ppp_netif(pcb);
  138. switch (err_code)
  139. {
  140. case PPPERR_NONE: /* Connected */
  141. pppdev->pppif.mtu = pppif->mtu;
  142. ppp_netdev_refresh(&pppdev->pppif);
  143. LOG_I("ppp_device connect successfully.");
  144. break;
  145. case PPPERR_PARAM:
  146. LOG_E("Invalid parameter.");
  147. break;
  148. case PPPERR_OPEN:
  149. LOG_E("Unable to open PPP session.");
  150. break;
  151. case PPPERR_DEVICE:
  152. LOG_E("Invalid I/O device for PPP.");
  153. break;
  154. case PPPERR_ALLOC:
  155. LOG_E("Unable to allocate resources.");
  156. break;
  157. case PPPERR_USER:
  158. LOG_D("User interrupt");
  159. break;
  160. case PPPERR_CONNECT: /* Connection lost */
  161. LOG_E("ppp connect lost.");
  162. break;
  163. case PPPERR_AUTHFAIL:
  164. LOG_E("Failed authentication challenge.");
  165. break;
  166. case PPPERR_PROTOCOL:
  167. LOG_E("Failed to meet protocol.");
  168. break;
  169. case PPPERR_PEERDEAD:
  170. LOG_E("Connection timeout.");
  171. break;
  172. case PPPERR_IDLETIMEOUT:
  173. LOG_E("Idle Timeout.");
  174. break;
  175. case PPPERR_CONNECTTIME:
  176. LOG_E("Max connect time reached.");
  177. break;
  178. case PPPERR_LOOPBACK:
  179. LOG_E("Loopback detected.");
  180. break;
  181. default:
  182. LOG_E("Unknown error code %d.", err_code);
  183. break;
  184. }
  185. if (err_code != PPPERR_NONE)
  186. rt_event_send(&pppdev->event, PPP_EVENT_LOST);
  187. }
  188. /*
  189. * prepare for starting recieve ppp frame, clear recieve buff and set ppp device state
  190. *
  191. * @param struct ppp_device *device
  192. *
  193. * @return NULL
  194. *
  195. */
  196. static inline void ppp_start_receive_frame(struct ppp_device *device)
  197. {
  198. device->rxpos = 0;
  199. device->state = PPP_STATE_WAIT_HEAD;
  200. }
  201. #ifdef PPP_DEVICE_DEBUG_DROP
  202. /*
  203. * ppp_show_dropbuf, printf the data whom ppp devcie drop out, and increase drop data conut
  204. *
  205. * @param struct ppp_device *device
  206. *
  207. * @return NULL
  208. */
  209. static inline void ppp_show_dropbuf(struct ppp_device *device)
  210. {
  211. if (!device->droppos)
  212. return;
  213. LOG_D("DROP: ");
  214. ppp_debug_hexdump(device->dropbuf, device->droppos);
  215. device->dropcnt += device->droppos;
  216. device->droppos = 0;
  217. }
  218. /*
  219. * ppp_show_rxbuf_as_drop, printf the data whom ppp devcie drop out, and increase drop data conut
  220. *
  221. * @param struct ppp_device *device
  222. *
  223. * @return NULL
  224. *
  225. */
  226. static inline void ppp_show_rxbuf_as_drop(struct ppp_device *device)
  227. {
  228. if (!device->rxpos)
  229. return;
  230. LOG_D("DROP: ");
  231. ppp_debug_hexdump(device->rxbuf, device->rxpos);
  232. device->dropcnt += device->rxpos;
  233. device->rxpos = 0;
  234. }
  235. /*
  236. * ppp_rxbuf_drop, printf the data whom ppp devcie drop out
  237. *
  238. * @param struct ppp_device *device
  239. *
  240. * @return NULL
  241. *
  242. */
  243. static inline void ppp_rxbuf_drop(struct ppp_device *device)
  244. {
  245. /* if we have no enough drop-buffer, we should display and clear drop-buffer */
  246. if (PPP_DROP_BUF - device->droppos < device->rxpos)
  247. {
  248. ppp_show_dropbuf(device);
  249. /* if our drop-buffer size less than or equal current valid size of rx-buffer,
  250. we should display and clear rx-buffer */
  251. if (PPP_DROP_BUF <= device->rxpos)
  252. {
  253. ppp_show_rxbuf_as_drop(device);
  254. }
  255. }
  256. if (device->rxpos)
  257. {
  258. rt_memcpy(&device->dropbuf[device->droppos], device->rxbuf, device->rxpos);
  259. device->droppos += device->rxpos;
  260. device->rxpos = 0;
  261. if (device->droppos == PPP_DROP_BUF)
  262. {
  263. ppp_show_dropbuf(device);
  264. }
  265. }
  266. ppp_start_receive_frame(device);
  267. }
  268. #else
  269. static inline void ppp_show_dropbuf(struct ppp_device *device) {}
  270. #define ppp_rxbuf_drop(device) ppp_start_receive_frame(device)
  271. #endif /* PPP_DEVICE_DEBUG_DROP */
  272. /*
  273. * ppp_processdata_enter, prepare to recieve data
  274. *
  275. * @param struct ppp_device *device
  276. *
  277. * @return NULL
  278. *
  279. */
  280. static inline void ppp_processdata_enter(struct ppp_device *device)
  281. {
  282. ppp_start_receive_frame(device);
  283. #ifdef PPP_DEVICE_DEBUG_DROP
  284. device->droppos = 0;
  285. #endif
  286. }
  287. /*
  288. * ppp_processdata_leave, throw ppp device data when ppp connection is closed
  289. *
  290. * @param struct ppp_device *device
  291. *
  292. * @return NULL
  293. *
  294. */
  295. static inline void ppp_processdata_leave(struct ppp_device *device)
  296. {
  297. ppp_rxbuf_drop(device);
  298. ppp_show_dropbuf(device);
  299. }
  300. /*
  301. * ppp_savebyte, save this data into ppp device buff
  302. *
  303. * @param struct ppp_device *device
  304. * rt_uint8_t dat
  305. *
  306. * @return NULL
  307. *
  308. */
  309. static inline void ppp_savebyte(struct ppp_device *device, rt_uint8_t dat)
  310. {
  311. RT_ASSERT(device->rxpos < sizeof(device->rxbuf));
  312. device->rxbuf[device->rxpos++] = dat;
  313. }
  314. /*
  315. * ppp_recv_processdata, save data from uart, recieve complete ppp frame data
  316. *
  317. * @param struct ppp_device *device
  318. * const rt_uint8_t *buf
  319. * rt_size_t len
  320. *
  321. * @return NULL
  322. *
  323. */
  324. static void ppp_recv_processdata(struct ppp_device *device, const rt_uint8_t *buf, rt_size_t len)
  325. {
  326. rt_uint8_t dat;
  327. while (len--)
  328. {
  329. dat = *buf++;
  330. process_dat:
  331. switch (device->state)
  332. {
  333. case PPP_STATE_WAIT_HEAD:
  334. ppp_savebyte(device, dat);
  335. if (dat == PPP_DATA_BEGIN_END) /* if recieve 0x7e */
  336. {
  337. ppp_show_dropbuf(device);
  338. device->state = PPP_STATE_RECV_DATA; /* begin recieve the second data */
  339. }
  340. else
  341. {
  342. ppp_rxbuf_drop(device);
  343. }
  344. break;
  345. case PPP_STATE_RECV_DATA:
  346. if (dat == PPP_DATA_BEGIN_END && device->rxpos == 1) /* if we recieve 0x7e when this data is the second data */
  347. {
  348. LOG_D("found continuous 0x7e");
  349. // start receive a new frame
  350. ppp_rxbuf_drop(device); /* throw this data, because 0x7e is the begin of ppp frame, the second data shouldn't been 0x7e */
  351. goto process_dat;
  352. }
  353. ppp_savebyte(device, dat);
  354. if (dat == PPP_DATA_BEGIN_END) /* the end of ppp frame */
  355. {
  356. #ifdef PPP_DEVICE_DEBUG_RX
  357. LOG_D("RX:");
  358. ppp_debug_hexdump(device->rxbuf, device->rxpos);
  359. #endif
  360. rt_enter_critical();
  361. pppos_input_tcpip(device->pcb, (u8_t *)device->rxbuf, device->rxpos);
  362. rt_exit_critical();
  363. ppp_start_receive_frame(device);
  364. }
  365. break;
  366. default:
  367. LOG_E("BUG: unexpect state: %u", (unsigned int)device->state);
  368. }
  369. if (device->rxpos == sizeof(device->rxbuf))
  370. {
  371. LOG_W("receive ppp frame is lagger than %u", (unsigned int)sizeof(device->rxbuf));
  372. ppp_rxbuf_drop(device);
  373. }
  374. }
  375. }
  376. /*
  377. * Receive thread , store uart data and transform tcpip stack
  378. *
  379. * @param ppp_device *device
  380. *
  381. *
  382. * @return 0: execute successful
  383. *
  384. */
  385. static int ppp_recv_entry(struct ppp_device *device)
  386. {
  387. const rt_uint32_t interested_event = PPP_EVENT_RX_NOTIFY | PPP_EVENT_LOST | PPP_EVENT_CLOSE_REQ;
  388. rt_uint32_t event;
  389. rt_size_t len;
  390. rt_uint8_t buffer[PPP_RECV_READ_MAX];
  391. rt_bool_t closing = RT_FALSE;
  392. rt_event_control(&device->event, RT_IPC_CMD_RESET, RT_NULL);
  393. device->state = PPP_STATE_PREPARE;
  394. while (1)
  395. {
  396. if (device->state == PPP_STATE_PREPARE)
  397. {
  398. if (!device->ops->prepare || device->ops->prepare(device) == RT_EOK)
  399. {
  400. ppp_processdata_enter(device);
  401. pppapi_connect(device->pcb, 0);
  402. }
  403. else
  404. {
  405. LOG_E("%s prepare fail, try again later", device->parent.parent.name);
  406. rt_thread_mdelay(10*1000);
  407. }
  408. continue;
  409. }
  410. rt_event_recv(&device->event, interested_event, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
  411. if (event & PPP_EVENT_RX_NOTIFY)
  412. {
  413. do
  414. {
  415. len = rt_device_read(device->uart, 0, buffer, PPP_RECV_READ_MAX);
  416. if (len)
  417. ppp_recv_processdata(device, buffer, len);
  418. } while (len);
  419. }
  420. if (event & PPP_EVENT_CLOSE_REQ)
  421. {
  422. LOG_D("user request close ppp");
  423. closing = RT_TRUE;
  424. pppapi_close(device->pcb, 0);
  425. }
  426. if (event & PPP_EVENT_LOST)
  427. {
  428. ppp_processdata_leave(device);
  429. if (closing)
  430. {
  431. LOG_W("ppp closing success");
  432. rt_event_send(&device->event, PPP_EVENT_CLOSED);
  433. break;
  434. }
  435. LOG_W("ppp lost, try reconnect");
  436. device->state = PPP_STATE_PREPARE;
  437. }
  438. }
  439. return RT_EOK;
  440. }
  441. /*
  442. * Creat a thread to creat receive thread function
  443. *
  444. * @param ppp_device *device
  445. *
  446. *
  447. * @return 0: execute successful
  448. *
  449. */
  450. static int ppp_recv_entry_creat(struct ppp_device *device)
  451. {
  452. rt_int8_t result = RT_EOK;
  453. /* dynamic creat a recv_thread */
  454. device->recv_tid = rt_thread_create("ppp_recv",
  455. (void (*)(void *parameter))ppp_recv_entry,
  456. device,
  457. 768,
  458. 8,
  459. 20);
  460. if (device->recv_tid == RT_NULL)
  461. {
  462. LOG_E("PPP device initialize failed! ppp_device_recv_tid create failed!");
  463. result = -RT_ENOMEM;
  464. goto __exit;
  465. }
  466. /* if you create a thread, never forget to start it */
  467. result = rt_thread_startup(device->recv_tid);
  468. if(result != RT_EOK)
  469. goto __exit;
  470. return result;
  471. __exit:
  472. rt_memset(device, 0x00, sizeof(struct ppp_device));
  473. return result;
  474. }
  475. /**
  476. * ppp device init function,set ops funciton and base config
  477. *
  478. * @param dev the pointer of device driver structure
  479. *
  480. *
  481. * @return 0: execute successful
  482. *
  483. */
  484. static rt_err_t ppp_device_init(struct rt_device *device)
  485. {
  486. RT_ASSERT(device != RT_NULL);
  487. struct ppp_device *ppp_device = (struct ppp_device *)device;
  488. RT_ASSERT(ppp_device != RT_NULL);
  489. device->flag |= RT_DEVICE_FLAG_STANDALONE;
  490. #ifdef PPP_DEVICE_DEBUG_DROP
  491. ppp_device->dropcnt = 0;
  492. ppp_device->droppos = 0;
  493. #endif
  494. return RT_EOK;
  495. }
  496. /*
  497. * initialize ppp device and set callback function
  498. *
  499. * @param rt_device_t *device
  500. * rt_uint16_t oflag
  501. *
  502. * @return 0: execute successful
  503. *
  504. */
  505. static rt_err_t ppp_device_open(struct rt_device *device, rt_uint16_t oflag)
  506. {
  507. int result = RT_EOK;
  508. rt_uint16_t uart_oflag;
  509. RT_ASSERT(device != RT_NULL);
  510. struct ppp_device *ppp_device = (struct ppp_device *)device;
  511. uart_oflag = RT_DEVICE_OFLAG_RDWR;
  512. if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_RX)
  513. uart_oflag |= RT_DEVICE_FLAG_DMA_RX;
  514. else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_RX)
  515. uart_oflag = RT_DEVICE_FLAG_INT_RX;
  516. if (ppp_device->uart->flag & RT_DEVICE_FLAG_DMA_TX)
  517. uart_oflag |= RT_DEVICE_FLAG_DMA_TX;
  518. else if (ppp_device->uart->flag & RT_DEVICE_FLAG_INT_TX)
  519. uart_oflag |= RT_DEVICE_FLAG_INT_TX;
  520. if (rt_device_open(ppp_device->uart, uart_oflag) != RT_EOK)
  521. {
  522. LOG_E("ppp device open failed.");
  523. result = -RT_ERROR;
  524. goto __exit;
  525. }
  526. rt_event_init(&ppp_device->event, "pppev", RT_IPC_FLAG_FIFO);
  527. /* we can do nothing */
  528. RT_ASSERT(ppp_device->uart && ppp_device->uart->type == RT_Device_Class_Char);
  529. /* uart transfer into tcpip protocol stack */
  530. rt_device_set_rx_indicate(ppp_device->uart, ppp_device_rx_ind);
  531. LOG_D("(%s) is used by ppp_device.", ppp_device->uart->parent.name);
  532. /* creat pppos */
  533. ppp_device->pcb = pppapi_pppos_create(&(ppp_device->pppif), ppp_data_send, ppp_status_changed, ppp_device);
  534. if (ppp_device->pcb == RT_NULL)
  535. {
  536. LOG_E("Create ppp pcb failed.");
  537. result = -RT_ERROR;
  538. goto __exit;
  539. }
  540. LOG_D("pppapi_pppos_create has created a protocol control block.");
  541. ppp_netdev_add(&ppp_device->pppif);
  542. /* set netif name */
  543. ppp_device->pppif.name[0] = ppp_device->parent.parent.name[0];
  544. ppp_device->pppif.name[1] = ppp_device->parent.parent.name[1];
  545. /* set default route */
  546. result = pppapi_set_default(ppp_device->pcb);
  547. if (result != RT_EOK)
  548. {
  549. LOG_E("pppapi_set_default execute failed.");
  550. result = -RT_ERROR;
  551. goto __exit;
  552. }
  553. LOG_D("pppapi_set_default has set a default route.");
  554. /* dns */
  555. ppp_set_usepeerdns(ppp_device->pcb, 1);
  556. LOG_D("ppp_set_usepeerdns has set a dns number.");
  557. #ifdef USING_PPP_AUTHORIZE
  558. /* set authorize */
  559. #if PAP_SUPPORT
  560. ppp_set_auth(ppp_device->pcb , PPPAUTHTYPE_PAP, ppp_device->config.user_name, ppp_device->config.user_name);
  561. #elif CHAP_SUPPORT
  562. ppp_set_auth(ppp_device->pcb, PPPAUTHTYPE_CHAP, ppp_device->config.user_name, ppp_device->config.user_name);
  563. #else
  564. #error "Unsupported AUTH Negotiation"
  565. #endif
  566. LOG_D("ppp_set_auth has passed verification.");
  567. #endif /* PPP_AUTHORIZE */
  568. /* Creat a thread to creat ppp recieve function */
  569. result = ppp_recv_entry_creat(ppp_device);
  570. if (result != RT_EOK)
  571. {
  572. LOG_E("Creat a thread to creat ppp recieve function failed.");
  573. result = -RT_ERROR;
  574. goto __exit;
  575. }
  576. LOG_D("Creat a thread to creat ppp recieve function successful.");
  577. __exit:
  578. return result;
  579. }
  580. /*
  581. * Close ppp device
  582. *
  583. * @param rt_device_t *device
  584. *
  585. *
  586. * @return 0: execute successful
  587. */
  588. static rt_err_t ppp_device_close(struct rt_device *device)
  589. {
  590. rt_uint32_t event;
  591. RT_ASSERT(device != RT_NULL);
  592. extern void ppp_netdev_del(struct netif *ppp_netif);
  593. struct ppp_device *ppp_device = (struct ppp_device *)device;
  594. RT_ASSERT(ppp_device != RT_NULL);
  595. rt_event_send(&ppp_device->event, PPP_EVENT_CLOSE_REQ);
  596. rt_event_recv(&ppp_device->event, PPP_EVENT_CLOSED, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, RT_WAITING_FOREVER, &event);
  597. rt_device_set_rx_indicate(ppp_device->uart, RT_NULL);
  598. ppp_netdev_del(&ppp_device->pppif);
  599. ppp_free(ppp_device->pcb);
  600. LOG_D("ppp netdev has been detach.");
  601. rt_event_detach(&ppp_device->event);
  602. rt_device_close(ppp_device->uart);
  603. /* cut down piont to piont at data link layer */
  604. LOG_I("ppp_device has been closed.");
  605. return RT_EOK;
  606. }
  607. /*
  608. * Control ppp device , access ppp mode or accsee AT mode
  609. *
  610. * @param rt_device_t *device
  611. * int cmd
  612. * void *args
  613. *
  614. * @return 0: execute successful
  615. */
  616. static rt_err_t ppp_device_control(struct rt_device *device,int cmd, void *args)
  617. {
  618. RT_ASSERT(device != RT_NULL);
  619. return -RT_ENOSYS;
  620. }
  621. /*
  622. * ppp device ops
  623. *
  624. */
  625. #ifdef RT_USING_DEVICE_OPS
  626. const struct rt_device_ops ppp_device_ops =
  627. {
  628. ppp_device_init,
  629. ppp_device_open,
  630. ppp_device_close,
  631. ppp_device_control
  632. };
  633. #endif
  634. /*
  635. * Register ppp_device into rt_device frame,set ops function to rt_device inferface
  636. *
  637. * @param struct ppp_device *ppp_device
  638. *
  639. * @return 0: execute successful
  640. *
  641. */
  642. int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, const char *uart_name, void *user_data)
  643. {
  644. RT_ASSERT(ppp_device != RT_NULL);
  645. rt_err_t result = RT_EOK;
  646. struct rt_device *device = RT_NULL;
  647. device = &(ppp_device->parent);
  648. device->type = RT_Device_Class_NetIf;
  649. #ifdef RT_USING_DEVICE_OPS
  650. device->ops = &ppp_device_ops;
  651. #else
  652. device->init = ppp_device_init;
  653. device->open = ppp_device_open;
  654. device->close = ppp_device_close;
  655. device->read = RT_NULL;
  656. device->write = RT_NULL;
  657. device->control = ppp_device_control;
  658. #endif
  659. /* now we supprot only one device */
  660. if (_g_ppp_device != RT_NULL)
  661. {
  662. LOG_E("Only one device support.");
  663. RT_ASSERT(_g_ppp_device == RT_NULL);
  664. }
  665. /* attention: you can't use ppp_device as a server in you network, unless
  666. sim of the modem module used supprots getting public IP address. */
  667. /* register ppp device into rt_device frame */
  668. result = rt_device_register(&ppp_device->parent, dev_name, RT_DEVICE_OFLAG_RDWR);
  669. if( result == RT_EOK)
  670. {
  671. _g_ppp_device = ppp_device;
  672. LOG_I("ppp_device(%s) register successfully.", PPP_DEVICE_NAME);
  673. }
  674. return result;
  675. }
  676. /*
  677. * attach data interface device into ppp device frame
  678. *
  679. * @param struct ppp_device *ppp_device
  680. * char *uart_name
  681. * void *user_data
  682. * @return 0: execute successful
  683. * -1: error
  684. *
  685. */
  686. int ppp_device_attach(struct ppp_device *ppp_device, const char *uart_name, void *user_data)
  687. {
  688. RT_ASSERT(ppp_device != RT_NULL);
  689. ppp_device->uart = rt_device_find(uart_name);
  690. if (!ppp_device->uart)
  691. {
  692. LOG_E("ppp_device_attach, cannot found %s", uart_name);
  693. return -RT_ERROR;
  694. }
  695. ppp_device->user_data = user_data;
  696. if (rt_device_open(&ppp_device->parent, 0) != RT_EOK)
  697. {
  698. LOG_E("ppp_device_attach failed. Can't open device(%d)");
  699. return -RT_ERROR;
  700. }
  701. return RT_EOK;
  702. }
  703. /*
  704. * detach data interface device from ppp device frame
  705. *
  706. * @param struct ppp_device *ppp_device
  707. *
  708. * @return 0: execute successful
  709. * -1: error
  710. *
  711. */
  712. int ppp_device_detach(struct ppp_device *ppp_device)
  713. {
  714. RT_ASSERT(ppp_device != RT_NULL);
  715. if (rt_device_close(&ppp_device->parent) != RT_EOK)
  716. {
  717. LOG_E("ppp_device_detach failed. Can't open device.");
  718. return -RT_ERROR;
  719. }
  720. ppp_device->uart = RT_NULL;
  721. ppp_device->user_data = RT_NULL;
  722. return RT_EOK;
  723. }