at_device_ml307.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-12-16 Jonas first version
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <at_device_ml307.h>
  14. //#define AT_DEBUG
  15. #define LOG_TAG "at.dev.ml307"
  16. #include <at_log.h>
  17. #ifdef AT_DEVICE_USING_ML307
  18. #define ML307_AT_DEFAULT_TIMEOUT 1000
  19. #define ML307_WAIT_CONNECT_TIME 5000
  20. #define ML307_THREAD_STACK_SIZE 2048
  21. #define ML307_POWER_OFF RT_FALSE
  22. #define ML307_POWER_ON RT_TRUE
  23. #define ML307_POWER_ON_TIME 3
  24. #define ML307_POWER_OFF_TIME 4
  25. #define ML307_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX/2)
  26. /* AT+CSTT command default*/
  27. static char *CSTT_CHINA_MOBILE = "AT+CSTT=\"CMNET\"";
  28. static char *CSTT_CHINA_UNICOM = "AT+CSTT=\"UNINET\"";
  29. static char *CSTT_CHINA_TELECOM = "AT+CSTT=\"CTNET\"";
  30. static rt_bool_t ml307_get_power_state(struct at_device *device)
  31. {
  32. struct at_device_ml307 *ml307 = RT_NULL;
  33. ml307 = (struct at_device_ml307 *) device->user_data;
  34. return (!rt_pin_read(ml307->power_status_pin)) ? ML307_POWER_ON : ML307_POWER_OFF;
  35. }
  36. static void ml307_power_on(struct at_device *device)
  37. {
  38. struct at_device_ml307 *ml307 = RT_NULL;
  39. ml307 = (struct at_device_ml307 *) device->user_data;
  40. /* not nead to set pin configuration for ml307 device power on */
  41. if (ml307->power_pin == -1 || ml307->power_status_pin == -1)
  42. {
  43. return;
  44. }
  45. if(ml307_get_power_state(device) == ML307_POWER_ON)
  46. {
  47. return;
  48. }
  49. rt_pin_write(ml307->power_pin, PIN_HIGH);
  50. rt_thread_mdelay(ML307_POWER_ON_TIME * RT_TICK_PER_SECOND);
  51. rt_pin_write(ml307->power_pin, PIN_LOW);
  52. }
  53. static void ml307_power_off(struct at_device *device)
  54. {
  55. struct at_device_ml307 *ml307 = RT_NULL;
  56. ml307 = (struct at_device_ml307 *) device->user_data;
  57. do{
  58. /* not nead to set pin configuration for ml307 device power on */
  59. if (ml307->power_pin == -1 || ml307->power_status_pin == -1)
  60. {
  61. return;
  62. }
  63. if(ml307_get_power_state(device) == ML307_POWER_OFF)
  64. {
  65. return;
  66. }
  67. rt_pin_write(ml307->power_pin, PIN_HIGH);
  68. rt_thread_mdelay(ML307_POWER_OFF_TIME * RT_TICK_PER_SECOND);
  69. rt_pin_write(ml307->power_pin, PIN_LOW);
  70. rt_thread_mdelay(100);
  71. }while(ml307_get_power_state(device) != ML307_POWER_OFF);
  72. }
  73. static int ml307_check_link_status(struct at_device *device)
  74. {
  75. at_response_t resp = RT_NULL;
  76. struct at_device_ml307 *ml307 = RT_NULL;
  77. int result = -RT_ERROR;
  78. int link_stat = 0;
  79. RT_ASSERT(device);
  80. ml307 = (struct at_device_ml307 *)device->user_data;
  81. resp = at_create_resp(96, 0, rt_tick_from_millisecond(300));
  82. if (resp == RT_NULL)
  83. {
  84. LOG_E("no memory for resp create.");
  85. return -RT_ERROR;
  86. }
  87. if(at_obj_exec_cmd(device->client, resp, "AT+MIPCALL?") < 0)
  88. {
  89. result = -RT_ERROR;
  90. goto __exit;
  91. }
  92. if (at_resp_parse_line_args_by_kw(resp, "+MIPCALL:", "+MIPCALL: %d,%*d,%*s", &link_stat) > 0)
  93. {
  94. if (link_stat == 1)
  95. {
  96. result = RT_EOK;
  97. }
  98. }
  99. if(at_obj_exec_cmd(device->client, resp, "AT+CGACT?") < 0)
  100. {
  101. result = -RT_ERROR;
  102. goto __exit;
  103. }
  104. //+CGACT: 1,1
  105. if (at_resp_parse_line_args_by_kw(resp, "+CGACT:", "+CGACT: %d,%*d", &link_stat) > 0)
  106. {
  107. result = link_stat;
  108. }
  109. __exit:
  110. if(resp)
  111. {
  112. at_delete_resp(resp);
  113. }
  114. return(result);
  115. }
  116. /* ============================= ml307 network interface operations ============================= */
  117. /* set ml307 network interface device status and address information */
  118. static int ml307_netdev_set_info(struct netdev *netdev)
  119. {
  120. #define ML307_IMEI_RESP_SIZE 32
  121. #define ML307_IPADDR_RESP_SIZE 64
  122. #define ML307_DNS_RESP_SIZE 96
  123. #define ML307_INFO_RESP_TIMO rt_tick_from_millisecond(300)
  124. int result = RT_EOK;
  125. ip_addr_t addr;
  126. at_response_t resp = RT_NULL;
  127. struct at_device *device = RT_NULL;
  128. RT_ASSERT(netdev);
  129. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  130. if (device == RT_NULL)
  131. {
  132. LOG_E("get device(%s) failed.", netdev->name);
  133. return -RT_ERROR;
  134. }
  135. /* set network interface device status */
  136. netdev_low_level_set_status(netdev, RT_TRUE);
  137. netdev_low_level_set_link_status(netdev, RT_TRUE);
  138. netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
  139. resp = at_create_resp(ML307_IMEI_RESP_SIZE, 0, ML307_INFO_RESP_TIMO);
  140. if (resp == RT_NULL)
  141. {
  142. LOG_E("no memory for resp create.");
  143. result = -RT_ENOMEM;
  144. goto __exit;
  145. }
  146. /* set network interface device hardware address(IMEI) */
  147. {
  148. #define ML307_NETDEV_HWADDR_LEN 8
  149. #define ML307_IMEI_LEN 15
  150. char imei[ML307_IMEI_LEN] = {0};
  151. int i = 0, j = 0;
  152. /* send "AT+GSN" commond to get device IMEI */
  153. if (at_obj_exec_cmd(device->client, resp, "AT+GSN=1") < 0)
  154. {
  155. result = -RT_ERROR;
  156. goto __exit;
  157. }
  158. if(at_resp_parse_line_args_by_kw(resp, "+GSN:", "+GSN:%s", imei) <= 0)
  159. {
  160. LOG_E("ml307 device(%s) prase \"AT+GSN\" commands resposne data error.", device->name);
  161. result = -RT_ERROR;
  162. goto __exit;
  163. }
  164. LOG_D("ml307 device(%s) IMEI number: %s", device->name, imei);
  165. netdev->hwaddr_len = ML307_NETDEV_HWADDR_LEN;
  166. /* get hardware address by IMEI */
  167. for (i = 0, j = 0; i < ML307_NETDEV_HWADDR_LEN && j < ML307_IMEI_LEN; i++, j += 2)
  168. {
  169. if (j != ML307_IMEI_LEN - 1)
  170. {
  171. netdev->hwaddr[i] = (imei[j] - '0') * 10 + (imei[j + 1] - '0');
  172. }
  173. else
  174. {
  175. netdev->hwaddr[i] = (imei[j] - '0');
  176. }
  177. }
  178. }
  179. /* set network interface device IP address */
  180. {
  181. #define IP_ADDR_SIZE_MAX 16
  182. char ipaddr[IP_ADDR_SIZE_MAX] = {0};
  183. at_resp_set_info(resp, ML307_IPADDR_RESP_SIZE*2, 2, ML307_INFO_RESP_TIMO);
  184. /* send "AT+CIFSR" commond to get IP address */
  185. if (at_obj_exec_cmd(device->client, resp, "AT+CGPADDR=1") < 0)
  186. {
  187. result = -RT_ERROR;
  188. goto __exit;
  189. }
  190. if (at_resp_parse_line_args_by_kw(resp, "+CGPADDR:", "+CGPADDR: %*d,\"%[^\"]", ipaddr) <= 0)
  191. {
  192. LOG_E("ml307 device(%s) prase \"AT+CGPADDR=1\" commands resposne data error!", device->name);
  193. result = -RT_ERROR;
  194. goto __exit;
  195. }
  196. LOG_D("ml307 device(%s) IP address: %s", device->name, ipaddr);
  197. /* set network interface address information */
  198. inet_aton(ipaddr, &addr);
  199. netdev_low_level_set_ipaddr(netdev, &addr);
  200. }
  201. /* set network interface device dns server */
  202. {
  203. #define DNS_ADDR_SIZE_MAX 16
  204. char dns_server1[DNS_ADDR_SIZE_MAX] = {0}, dns_server2[DNS_ADDR_SIZE_MAX] = {0};
  205. char dns_str[DNS_ADDR_SIZE_MAX*3] = {0};
  206. at_resp_set_info(resp, ML307_DNS_RESP_SIZE, 0, ML307_INFO_RESP_TIMO);
  207. /* send "AT+MDNSCFG=\"priority\",0" commond to set resolve IPV4 address priority */
  208. if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"priority\",0") < 0)
  209. {
  210. result = -RT_ERROR;
  211. goto __exit;
  212. }
  213. /* send "AT+MDNSCFG=\"ip\"" commond to get DNS servers address */
  214. if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"ip\"") < 0)
  215. {
  216. result = -RT_ERROR;
  217. goto __exit;
  218. }
  219. //+MDNSCFG: "ip","183.230.126.224",,"183.230.126.225"
  220. if (at_resp_parse_line_args_by_kw(resp, "+MDNSCFG:", "+MDNSCFG: \"ip\",%s", dns_str) < 0)
  221. {
  222. result = -RT_ERROR;
  223. goto __exit;
  224. }
  225. const char *dns1_str = strstr(dns_str, "\"");
  226. rt_sscanf(dns1_str, "\"%[^\"]", dns_server1);
  227. const char *dns2_str = strstr(dns_str, "\",\"");
  228. rt_sscanf(dns2_str, "\",\"%[^\"]", dns_server2);
  229. LOG_D("ml307 device(%s) primary DNS server address: %s", device->name, dns_server1);
  230. LOG_D("ml307 device(%s) secondary DNS server address: %s", device->name, dns_server2);
  231. inet_aton(dns_server1, &addr);
  232. netdev_low_level_set_dns_server(netdev, 0, &addr);
  233. inet_aton(dns_server2, &addr);
  234. netdev_low_level_set_dns_server(netdev, 1, &addr);
  235. }
  236. __exit:
  237. if (resp)
  238. {
  239. at_delete_resp(resp);
  240. }
  241. return result;
  242. }
  243. static void check_link_status_entry(void *parameter)
  244. {
  245. #define ML307_LINK_STATUS_OK 1
  246. #define ML307_LINK_RESP_SIZE 128
  247. #define ML307_LINK_RESP_TIMO (3 * RT_TICK_PER_SECOND)
  248. #define ML307_LINK_DELAY_TIME (30 * RT_TICK_PER_SECOND)
  249. at_response_t resp = RT_NULL;
  250. int result_code, link_status;
  251. struct at_device *device = RT_NULL;
  252. struct netdev *netdev = (struct netdev *)parameter;
  253. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  254. if (device == RT_NULL)
  255. {
  256. LOG_E("get device(%s) failed.", netdev->name);
  257. return;
  258. }
  259. resp = at_create_resp(ML307_LINK_RESP_SIZE, 0, ML307_LINK_RESP_TIMO);
  260. if (resp == RT_NULL)
  261. {
  262. LOG_E("no memory for response create.");
  263. return;
  264. }
  265. while(1)
  266. {
  267. link_status = ml307_check_link_status(device);
  268. if(link_status < 0)
  269. {
  270. rt_thread_mdelay(ML307_LINK_DELAY_TIME);
  271. continue;
  272. }
  273. /* check the network interface device link status */
  274. if ((ML307_LINK_STATUS_OK == link_status) != netdev_is_link_up(netdev))
  275. {
  276. netdev_low_level_set_link_status(netdev, (ML307_LINK_STATUS_OK == link_status));
  277. }
  278. rt_thread_mdelay(ML307_LINK_DELAY_TIME);
  279. }
  280. }
  281. static int ml307_netdev_check_link_status(struct netdev *netdev)
  282. {
  283. #define ML307_LINK_THREAD_TICK 20
  284. #define ML307_LINK_THREAD_STACK_SIZE (1024 + 512)
  285. #define ML307_LINK_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX - 2)
  286. rt_thread_t tid;
  287. char tname[RT_NAME_MAX] = {0};
  288. if (netdev == RT_NULL)
  289. {
  290. LOG_E("input network interface device is NULL.\n");
  291. return -RT_ERROR;
  292. }
  293. rt_snprintf(tname, RT_NAME_MAX, "%s_link", netdev->name);
  294. tid = rt_thread_create(tname, check_link_status_entry, (void *) netdev,
  295. ML307_LINK_THREAD_STACK_SIZE, ML307_LINK_THREAD_PRIORITY, ML307_LINK_THREAD_TICK);
  296. if (tid)
  297. {
  298. rt_thread_startup(tid);
  299. }
  300. return RT_EOK;
  301. }
  302. static int ml307_net_init(struct at_device *device);
  303. static int ml307_netdev_set_up(struct netdev *netdev)
  304. {
  305. struct at_device *device = RT_NULL;
  306. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  307. if (device == RT_NULL)
  308. {
  309. LOG_E("get ml307 device by netdev name(%s) failed.", netdev->name);
  310. return -RT_ERROR;
  311. }
  312. if (device->is_init == RT_FALSE)
  313. {
  314. device->is_init = RT_TRUE;
  315. ml307_net_init(device);
  316. netdev_low_level_set_status(netdev, RT_TRUE);
  317. LOG_D("the network interface device(%s) set up status.", netdev->name);
  318. }
  319. return RT_EOK;
  320. }
  321. static int ml307_netdev_set_down(struct netdev *netdev)
  322. {
  323. struct at_device *device = RT_NULL;
  324. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  325. if (device == RT_NULL)
  326. {
  327. LOG_E("get ml307 device by netdev name(%s) failed.", netdev->name);
  328. return -RT_ERROR;
  329. }
  330. if (device->is_init == RT_TRUE)
  331. {
  332. ml307_power_off(device);
  333. device->is_init = RT_FALSE;
  334. netdev_low_level_set_status(netdev, RT_FALSE);
  335. LOG_D("the network interface device(%s) set down status.", netdev->name);
  336. }
  337. return RT_EOK;
  338. }
  339. static int ml307_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
  340. {
  341. #define ML307_DNS_RESP_LEN 8
  342. #define ML307_DNS_RESP_TIMEO rt_tick_from_millisecond(300)
  343. int result = RT_EOK;
  344. at_response_t resp = RT_NULL;
  345. struct at_device *device = RT_NULL;
  346. RT_ASSERT(netdev);
  347. RT_ASSERT(dns_server);
  348. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  349. if (device == RT_NULL)
  350. {
  351. LOG_E("get ml307 device by netdev name(%s) failed.", netdev->name);
  352. return -RT_ERROR;
  353. }
  354. resp = at_create_resp(ML307_DNS_RESP_LEN, 0, ML307_DNS_RESP_TIMEO);
  355. if (resp == RT_NULL)
  356. {
  357. LOG_D("ml307 set dns server failed, no memory for response object.");
  358. result = -RT_ENOMEM;
  359. goto __exit;
  360. }
  361. /* send "AT+CDNSCFG=<pri_dns>[,<sec_dns>]" commond to set dns servers */
  362. if (at_obj_exec_cmd(device->client, resp, "AT+MDNSCFG=\"%s\"", inet_ntoa(*dns_server)) < 0)
  363. {
  364. result = -RT_ERROR;
  365. goto __exit;
  366. }
  367. netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
  368. __exit:
  369. if (resp)
  370. {
  371. at_delete_resp(resp);
  372. }
  373. return result;
  374. }
  375. static int ml307_ping_domain_resolve(struct at_device *device, const char *name, char ip[16])
  376. {
  377. int result = RT_EOK;
  378. char recv_ip[16] = { 0 };
  379. at_response_t resp = RT_NULL;
  380. /* The maximum response time is 14 seconds, affected by network status */
  381. resp = at_create_resp(512, 4, 14 * RT_TICK_PER_SECOND);
  382. if (resp == RT_NULL)
  383. {
  384. LOG_E("no memory for ml307 device(%s) response structure.", device->name);
  385. return -RT_ENOMEM;
  386. }
  387. if (at_obj_exec_cmd(device->client, resp, "AT+CGACT?") < 0)
  388. {
  389. result = -RT_ERROR;
  390. goto __exit;
  391. }
  392. if (at_obj_exec_cmd(device->client, resp, "AT+MDNSGIP=\"%s\"", name) < 0)
  393. {
  394. result = -RT_ERROR;
  395. goto __exit;
  396. }
  397. if (at_resp_parse_line_args_by_kw(resp, "+MDNSGIP:", "%*[^,],\"%[^\"]", recv_ip) < 0)
  398. {
  399. rt_thread_mdelay(100);
  400. /* resolve failed, maybe receive an URC CRLF */
  401. }
  402. if (rt_strlen(recv_ip) < 8)
  403. {
  404. rt_thread_mdelay(100);
  405. /* resolve failed, maybe receive an URC CRLF */
  406. }
  407. else
  408. {
  409. rt_strncpy(ip, recv_ip, 15);
  410. ip[15] = '\0';
  411. }
  412. __exit:
  413. if (resp)
  414. {
  415. at_delete_resp(resp);
  416. }
  417. return result;
  418. }
  419. #ifdef NETDEV_USING_PING
  420. #ifdef AT_DEVICE_USING_ML307
  421. static int ml307_netdev_ping(struct netdev *netdev, const char *host,
  422. size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp
  423. #if RT_VER_NUM >= 0x50100
  424. , rt_bool_t is_bind
  425. #endif
  426. )
  427. {
  428. #define ML307_PING_RESP_SIZE 128
  429. #define ML307_PING_IP_SIZE 16
  430. #define ML307_PING_TIMEO (5 * RT_TICK_PER_SECOND)
  431. int result = -RT_ERROR;
  432. int response, time, ttl, bytes;
  433. char ip_addr[ML307_PING_IP_SIZE] = {0};
  434. char ip_addr_resp[ML307_PING_IP_SIZE + 8] = {0};
  435. at_response_t resp = RT_NULL;
  436. struct at_device *device = RT_NULL;
  437. #if RT_VER_NUM >= 0x50100
  438. RT_UNUSED(is_bind);
  439. #endif
  440. RT_ASSERT(netdev);
  441. RT_ASSERT(host);
  442. RT_ASSERT(ping_resp);
  443. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  444. if (device == RT_NULL)
  445. {
  446. LOG_E("get device(%s) failed.", netdev->name);
  447. return -RT_ERROR;
  448. }
  449. /* Response line number set six because no \r\nOK\r\n at the end*/
  450. resp = at_create_resp(ML307_PING_RESP_SIZE, 4, ML307_PING_TIMEO);
  451. if (resp == RT_NULL)
  452. {
  453. LOG_E("no memory for resp create.");
  454. result = -RT_ERROR;
  455. goto __exit;
  456. }
  457. /* send "AT+MPING="<host>"[,[<timeout>][,<pingnum>]]" timeout:1-255 second, pingnum:1-10, commond to send ping request */
  458. if(ml307_ping_domain_resolve(device, host, ip_addr) == RT_EOK)
  459. {
  460. at_obj_exec_cmd(device->client, resp, "AT+MPING=\"%s\", 10, 1", ip_addr);
  461. }
  462. else
  463. {
  464. at_obj_exec_cmd(device->client, resp, "AT+MPING=\"%s\", 10, 1", host);
  465. }
  466. rt_sscanf(at_resp_get_line_by_kw(resp, "+MPING:"), "+MPING:%d,%*s", &response);
  467. switch (response)
  468. {
  469. case 0:
  470. if (at_resp_parse_line_args(resp, 4, "+MPING: %d, %[^,], %d, %d, %d",
  471. &response, ip_addr_resp, &bytes, &time, &ttl) != RT_NULL)
  472. {
  473. rt_sscanf(ip_addr_resp, "%[^\"]", ip_addr);
  474. /* ping result reponse at the sixth line */
  475. // if (at_resp_parse_line_args(resp, 12, "+MPING: %*[^,], %d, %d, %d, %d, %d",
  476. // &sent, &lost, &min, &max, &avg) != RT_NULL)
  477. // {
  478. //
  479. // }
  480. inet_aton(ip_addr, &(ping_resp->ip_addr));
  481. ping_resp->data_len = bytes;
  482. ping_resp->ticks = time;
  483. ping_resp->ttl = ttl;
  484. result = RT_EOK;
  485. }
  486. break;
  487. case 1:
  488. LOG_E("%s device DNS resolution failed.", device->name);
  489. break;
  490. case 2:
  491. LOG_E("%s device DNS resolution timeout.", device->name);
  492. break;
  493. case 3:
  494. LOG_E("%s device Response error.", device->name);
  495. break;
  496. case 4:
  497. LOG_E("%s device Response timeout.", device->name);
  498. break;
  499. case 5:
  500. LOG_E("%s device Other errors.", device->name);
  501. break;
  502. default:
  503. break;
  504. }
  505. __exit:
  506. if (resp)
  507. {
  508. at_delete_resp(resp);
  509. }
  510. return result;
  511. }
  512. #endif
  513. #endif /* NETDEV_USING_PING */
  514. #ifdef NETDEV_USING_NETSTAT
  515. void ml307_netdev_netstat(struct netdev *netdev)
  516. {
  517. #define ML307_NETSTAT_RESP_SIZE 320
  518. #define ML307_NETSTAT_TYPE_SIZE 4
  519. #define ML307_NETSTAT_IPADDR_SIZE 17
  520. #define ML307_NETSTAT_EXPRESSION "+MIPSTATE:%*d,\"%[^\"]\",\"%[^\"]\",%d,%d"
  521. at_response_t resp = RT_NULL;
  522. struct at_device *device = RT_NULL;
  523. int remote_port = 0, link_sta, i;
  524. char *type = RT_NULL;
  525. char *ipaddr = RT_NULL;
  526. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  527. if (device == RT_NULL)
  528. {
  529. LOG_E("get device(%s) failed.", netdev->name);
  530. return;
  531. }
  532. type = (char *) rt_calloc(1, ML307_NETSTAT_TYPE_SIZE);
  533. ipaddr = (char *) rt_calloc(1, ML307_NETSTAT_IPADDR_SIZE);
  534. if ((type && ipaddr) == RT_NULL)
  535. {
  536. LOG_E("no memory for ipaddr create.");
  537. goto __exit;
  538. }
  539. resp = at_create_resp(ML307_NETSTAT_RESP_SIZE, 0, 5 * RT_TICK_PER_SECOND);
  540. if (resp == RT_NULL)
  541. {
  542. LOG_E("no memory for resp create.", device->name);
  543. goto __exit;
  544. }
  545. /* send network connection information commond "AT+MIPSTATE?" and wait response */
  546. if (at_obj_exec_cmd(device->client, resp, "AT+MIPSTATE?") < 0)
  547. {
  548. goto __exit;
  549. }
  550. for (i = 1; i <= resp->line_counts; i++)
  551. {
  552. if (strstr(at_resp_get_line(resp, i), "+MIPSTATE:"))
  553. {
  554. /* parse the third line of response data, get the network connection information */
  555. if (at_resp_parse_line_args(resp, i, ML307_NETSTAT_EXPRESSION, type, ipaddr, &remote_port, &link_sta) < 0)
  556. {
  557. goto __exit;
  558. }
  559. else
  560. {
  561. /* link_sta==2?"LINK_INTNET_UP":"LINK_INTNET_DOWN" */
  562. LOG_RAW("%s: %s ==> %s:%d\n", type, inet_ntoa(netdev->ip_addr), ipaddr, remote_port);
  563. }
  564. }
  565. }
  566. __exit:
  567. if (resp)
  568. {
  569. at_delete_resp(resp);
  570. }
  571. if (type)
  572. {
  573. rt_free(type);
  574. }
  575. if (ipaddr)
  576. {
  577. rt_free(ipaddr);
  578. }
  579. }
  580. #endif /* NETDEV_USING_NETSTAT */
  581. const struct netdev_ops ml307_netdev_ops =
  582. {
  583. ml307_netdev_set_up,
  584. ml307_netdev_set_down,
  585. RT_NULL, /* not support set ip, netmask, gatway address */
  586. ml307_netdev_set_dns_server,
  587. RT_NULL, /* not support set DHCP status */
  588. #ifdef NETDEV_USING_PING
  589. ml307_netdev_ping,
  590. #endif
  591. #ifdef NETDEV_USING_NETSTAT
  592. ml307_netdev_netstat,
  593. #endif
  594. };
  595. static struct netdev *ml307_netdev_add(const char *netdev_name)
  596. {
  597. #define ML307_NETDEV_MTU 1500
  598. struct netdev *netdev = RT_NULL;
  599. RT_ASSERT(netdev_name);
  600. netdev = netdev_get_by_name(netdev_name);
  601. if (netdev != RT_NULL)
  602. {
  603. return (netdev);
  604. }
  605. netdev = (struct netdev *) rt_calloc(1, sizeof(struct netdev));
  606. if (netdev == RT_NULL)
  607. {
  608. LOG_E("no memory for ml307 device(%s) netdev structure.", netdev_name);
  609. return RT_NULL;
  610. }
  611. netdev->mtu = ML307_NETDEV_MTU;
  612. netdev->ops = &ml307_netdev_ops;
  613. #ifdef SAL_USING_AT
  614. extern int sal_at_netdev_set_pf_info(struct netdev *netdev);
  615. /* set the network interface socket/netdb operations */
  616. sal_at_netdev_set_pf_info(netdev);
  617. #endif
  618. netdev_register(netdev, netdev_name, RT_NULL);
  619. return netdev;
  620. }
  621. /* ============================= ml307 device operations ============================= */
  622. #define AT_SEND_CMD(client, resp, resp_line, timeout, cmd) \
  623. do { \
  624. (resp) = at_resp_set_info((resp), 128, (resp_line), rt_tick_from_millisecond(timeout)); \
  625. if (at_obj_exec_cmd((client), (resp), (cmd)) < 0) \
  626. { \
  627. result = -RT_ERROR; \
  628. goto __exit; \
  629. } \
  630. } while(0) \
  631. /* init for ml307 */
  632. static void ml307_init_thread_entry(void *parameter)
  633. {
  634. #define INIT_RETRY 5
  635. #define CPIN_RETRY 10
  636. #define CSQ_RETRY 10
  637. #define CREG_RETRY 10
  638. #define CGREG_RETRY 20
  639. #define IPADDR_RETRY 10
  640. #define CGATT_RETRY 10
  641. #define COMMON_RETRY 10
  642. int i, qimux, retry_num = INIT_RETRY;
  643. char parsed_data[10] = {0};
  644. rt_err_t result = RT_EOK;
  645. at_response_t resp = RT_NULL;
  646. struct at_device *device = (struct at_device *)parameter;
  647. struct at_client *client = device->client;
  648. resp = at_create_resp(128, 0, rt_tick_from_millisecond(500));
  649. if (resp == RT_NULL)
  650. {
  651. LOG_E("no memory for ml307 device(%s) response structure.", device->name);
  652. return;
  653. }
  654. LOG_D("start initializing the device(%s)", device->name);
  655. ml307_power_off(device);
  656. while (retry_num--)
  657. {
  658. rt_memset(parsed_data, 0, sizeof(parsed_data));
  659. rt_thread_mdelay(500);
  660. ml307_power_on(device);
  661. rt_thread_mdelay(1000);
  662. /* wait ml307 startup finish */
  663. if (at_client_obj_wait_connect(client, ML307_WAIT_CONNECT_TIME))
  664. {
  665. result = -RT_ETIMEOUT;
  666. goto __exit;
  667. }
  668. /* disable echo */
  669. AT_SEND_CMD(client, resp, 0, ML307_AT_DEFAULT_TIMEOUT, "ATE0");
  670. /* get module version */
  671. AT_SEND_CMD(client, resp, 4, 2*ML307_AT_DEFAULT_TIMEOUT, "ATI");
  672. /* show module version */
  673. for (i = 0; i < (int)resp->line_counts - 1; i++)
  674. {
  675. LOG_D("%s", at_resp_get_line(resp, i + 1));
  676. }
  677. /* check SIM card */
  678. for (i = 0; i < CPIN_RETRY; i++)
  679. {
  680. AT_SEND_CMD(client, resp, 2, 5 * RT_TICK_PER_SECOND, "AT+CPIN?");
  681. if (at_resp_get_line_by_kw(resp, "READY"))
  682. {
  683. LOG_I("ml307 device(%s) SIM card detection success.", device->name);
  684. break;
  685. }
  686. rt_thread_mdelay(500);
  687. }
  688. if (i == CPIN_RETRY)
  689. {
  690. LOG_E("ml307 device(%s) SIM card detection failed.", device->name);
  691. result = -RT_ERROR;
  692. goto __exit;
  693. }
  694. /* check SIM card */
  695. for (i = 0; i < CPIN_RETRY; i++)
  696. {
  697. AT_SEND_CMD(client, resp, 2, 10 * 1000, "AT+ICCID");
  698. if (at_resp_get_line_by_kw(resp, "+ICCID:"))
  699. {
  700. LOG_D("%s device SIM card detection success.", device->name);
  701. break;
  702. }
  703. rt_thread_mdelay(1000);
  704. }
  705. if (i == CPIN_RETRY)
  706. {
  707. LOG_E("%s device SIM card detection failed.", device->name);
  708. result = -RT_ERROR;
  709. goto __exit;
  710. }
  711. /* check signal strength */
  712. for (i = 0; i < CSQ_RETRY; i++)
  713. {
  714. AT_SEND_CMD(client, resp, 0, 3*ML307_AT_DEFAULT_TIMEOUT, "AT+CSQ");
  715. at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ: %s", &parsed_data);
  716. if (rt_strncmp(parsed_data, "99,99", sizeof(parsed_data)))
  717. {
  718. LOG_D("signal strength: %s", parsed_data);
  719. break;
  720. }
  721. rt_thread_mdelay(2000);
  722. }
  723. if(i == CSQ_RETRY)
  724. {
  725. LOG_E("%s device signal strength check failed(%s).", device->name, parsed_data);
  726. result = -RT_ERROR;
  727. goto __exit;
  728. }
  729. /* check the GSM network is registered */
  730. // for (i = 0; i < CREG_RETRY; i++)
  731. // {
  732. // AT_SEND_CMD(client, resp, 0, ML307_AT_DEFAULT_TIMEOUT, "AT+CREG?");
  733. // at_resp_parse_line_args_by_kw(resp, "+CREG:", "+CREG: %s", &parsed_data);
  734. // if (!strncmp(parsed_data, "0,1", sizeof(parsed_data)) ||
  735. // !strncmp(parsed_data, "0,5", sizeof(parsed_data)))
  736. // {
  737. // LOG_D("ml307 device(%s) GSM network is registered(%s),", device->name, parsed_data);
  738. // break;
  739. // }
  740. // if(!strncmp(parsed_data, "0,3", sizeof(parsed_data)))
  741. // {
  742. // LOG_E("%s device GSM network is register failed(%s).", device->name, parsed_data);
  743. // result = -RT_ERROR;
  744. // goto __exit;
  745. // }
  746. // rt_thread_mdelay(1000 + 500 * (i + 1));
  747. // }
  748. // if (i == CREG_RETRY)
  749. // {
  750. // LOG_E("%s device GSM network is register failed(%s).", device->name, parsed_data);
  751. // result = -RT_ERROR;
  752. // goto __exit;
  753. // }
  754. //
  755. // /* check packet domain attach or detach */
  756. // for (i = 0; i < CGATT_RETRY; i++)
  757. // {
  758. // AT_SEND_CMD(client, resp, 0, ML307_AT_DEFAULT_TIMEOUT, "AT+CGATT?");
  759. // at_resp_parse_line_args_by_kw(resp, "+CGATT:", "+CGATT: %s", &parsed_data);
  760. // if (!rt_strncmp(parsed_data, "1", 1))
  761. // {
  762. // LOG_D("%s device Packet domain attach.", device->name);
  763. // break;
  764. // }
  765. //
  766. // rt_thread_mdelay(1000);
  767. // }
  768. // if (i == CGATT_RETRY)
  769. // {
  770. // LOG_E("%s device GPRS attach failed.", device->name);
  771. // result = -RT_ERROR;
  772. // goto __exit;
  773. // }
  774. /* Define PDP Context */
  775. // for (i = 0; i < COMMON_RETRY; i++)
  776. // {
  777. // if (at_obj_exec_cmd(client, resp, "AT+CGDCONT=1,\"IPV4V6\",\"cmnet\"") == RT_EOK)
  778. // {
  779. // LOG_D("%s device Define PDP Context Success.", device->name);
  780. // break;
  781. // }
  782. // rt_thread_mdelay(100);
  783. // }
  784. // if (i == COMMON_RETRY)
  785. // {
  786. // LOG_E("%s device Define PDP Context failed.", device->name);
  787. // result = -RT_ERROR;
  788. // goto __exit;
  789. // }
  790. //
  791. // /* PDP Context Activate*/
  792. // for (i = 0; i < COMMON_RETRY; i++)
  793. // {
  794. // if (at_obj_exec_cmd(client, resp, "AT+MIPCALL=1,1") == RT_EOK)
  795. // {
  796. // LOG_D("%s device PDP Context Activate Success.", device->name);
  797. // break;
  798. // }
  799. // rt_thread_mdelay(500);
  800. // }
  801. // if (i == COMMON_RETRY)
  802. // {
  803. // LOG_E("%s device PDP Context Activate failed.", device->name);
  804. // result = -RT_ERROR;
  805. // goto __exit;
  806. // }
  807. #if defined (AT_DEBUG)
  808. /* check the GPRS network IP address */
  809. for (i = 0; i < IPADDR_RETRY; i++)
  810. {
  811. if (at_obj_exec_cmd(client, resp, "AT+MIPCALL?") == RT_EOK)
  812. {
  813. #define IP_ADDR_SIZE_MAX 16
  814. char ipaddr_str[8*IP_ADDR_SIZE_MAX] = {0};
  815. char ipaddr_v4[IP_ADDR_SIZE_MAX] = {0};
  816. char ipaddr_v6[4*IP_ADDR_SIZE_MAX] = {0};
  817. /* parse response data "+CGPADDR: 1,<IP_address>" */
  818. if (at_resp_parse_line_args_by_kw(resp, "+MIPCALL:", "+MIPCALL: %*d,%*d,%s", ipaddr_str) > 0)
  819. {
  820. const char *ipaddr_v4_str = strstr(ipaddr_str, "\"");
  821. rt_sscanf(ipaddr_v4_str, "\"%[^\"]", ipaddr_v4);
  822. const char *ipaddr_v6_str = strstr(ipaddr_str, "\",\"");
  823. rt_sscanf(ipaddr_v6_str, "\",\"%[^\"]", ipaddr_v6);
  824. LOG_D("%s device IP address: %s - %s", device->name, ipaddr_v4, ipaddr_v6);
  825. break;
  826. }
  827. }
  828. rt_thread_mdelay(1000);
  829. }
  830. if (i == IPADDR_RETRY)
  831. {
  832. LOG_E("%s device GPRS is get IP address failed", device->name);
  833. result = -RT_ERROR;
  834. goto __exit;
  835. }
  836. #endif
  837. result = RT_EOK;
  838. __exit:
  839. if (result == RT_EOK)
  840. {
  841. break;
  842. }
  843. else
  844. {
  845. /* power off the ml307 device */
  846. ml307_power_off(device);
  847. rt_thread_mdelay(1000);
  848. LOG_I("ml307 device(%s) initialize retry...", device->name);
  849. }
  850. }
  851. if (resp)
  852. {
  853. at_delete_resp(resp);
  854. }
  855. if (result == RT_EOK)
  856. {
  857. device->is_init = RT_TRUE;
  858. /* set network interface device status and address information */
  859. ml307_netdev_set_info(device->netdev);
  860. /* */
  861. ml307_netdev_check_link_status(device->netdev);
  862. /* */
  863. LOG_I("ml307 device(%s) network initialize success!", device->name);
  864. }
  865. else
  866. {
  867. device->is_init = RT_FALSE;
  868. netdev_low_level_set_status(device->netdev, RT_FALSE);
  869. LOG_E("ml307 device(%s) network initialize failed(%d)!", device->name, result);
  870. }
  871. }
  872. static int ml307_net_init(struct at_device *device)
  873. {
  874. #ifdef AT_DEVICE_ML307_INIT_ASYN
  875. rt_thread_t tid;
  876. tid = rt_thread_create("ml307_net_init", ml307_init_thread_entry, (void *)device,
  877. ML307_THREAD_STACK_SIZE, ML307_THREAD_PRIORITY, 20);
  878. if (tid)
  879. {
  880. rt_thread_startup(tid);
  881. }
  882. else
  883. {
  884. LOG_E("create ml307 device(%s) initialization thread failed.", device->name);
  885. return -RT_ERROR;
  886. }
  887. #else
  888. ml307_init_thread_entry(device);
  889. #endif /* AT_DEVICE_ML307_INIT_ASYN */
  890. return RT_EOK;
  891. }
  892. static void urc_func(struct at_client *client, const char *data, rt_size_t size)
  893. {
  894. RT_ASSERT(data);
  895. LOG_I("URC data : %.*s", size, data);
  896. }
  897. /* ml307 device URC table for the device control */
  898. static const struct at_urc urc_table[] =
  899. {
  900. {"READY", "\r\n", urc_func},
  901. };
  902. static int ml307_init(struct at_device *device)
  903. {
  904. struct at_device_ml307 *ml307 = (struct at_device_ml307 *) device->user_data;
  905. struct serial_configure serial_config = RT_SERIAL_CONFIG_DEFAULT;
  906. rt_device_t serial = rt_device_find(ml307->client_name);
  907. if (serial == RT_NULL)
  908. {
  909. LOG_E("ml307 device(%s) initialize failed, get AT client(%s) failed.", ml307->device_name, ml307->client_name);
  910. return -RT_ERROR;
  911. }
  912. serial_config.bufsz = ml307->recv_buff_size;
  913. rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &serial_config);
  914. /* initialize AT client */
  915. #if RT_VER_NUM >= 0x50100
  916. at_client_init(ml307->client_name, ml307->recv_buff_size, ml307->recv_buff_size);
  917. #else
  918. at_client_init(ml307->client_name, ml307->recv_buff_size);
  919. #endif
  920. device->client = at_client_get(ml307->client_name);
  921. if (device->client == RT_NULL)
  922. {
  923. LOG_E("ml307 device(%s) initialize failed, get AT client(%s) failed.", ml307->device_name, ml307->client_name);
  924. return -RT_ERROR;
  925. }
  926. /* register URC data execution function */
  927. at_obj_set_urc_table(device->client, urc_table, sizeof(urc_table) / sizeof(urc_table[0]));
  928. #ifdef AT_USING_SOCKET
  929. ml307_socket_init(device);
  930. #endif
  931. /* add ml307 device to the netdev list */
  932. device->netdev = ml307_netdev_add(ml307->device_name);
  933. if (device->netdev == RT_NULL)
  934. {
  935. LOG_E("ml307 device(%s) initialize failed, get network interface device failed.", ml307->device_name);
  936. return -RT_ERROR;
  937. }
  938. /* initialize ml307 pin configuration */
  939. if (ml307->power_pin != -1)
  940. {
  941. rt_pin_mode(ml307->power_pin, PIN_MODE_OUTPUT);
  942. }
  943. if (ml307->power_status_pin != -1)
  944. {
  945. rt_pin_mode(ml307->power_status_pin, PIN_MODE_INPUT_PULLUP);
  946. }
  947. /* initialize ml307 device network */
  948. return ml307_netdev_set_up(device->netdev);
  949. }
  950. static int ml307_deinit(struct at_device *device)
  951. {
  952. return ml307_netdev_set_down(device->netdev);
  953. }
  954. static int ml307_control(struct at_device *device, int cmd, void *arg)
  955. {
  956. int result = -RT_ERROR;
  957. RT_ASSERT(device);
  958. switch (cmd)
  959. {
  960. case AT_DEVICE_CTRL_POWER_ON:
  961. case AT_DEVICE_CTRL_POWER_OFF:
  962. case AT_DEVICE_CTRL_RESET:
  963. case AT_DEVICE_CTRL_LOW_POWER:
  964. case AT_DEVICE_CTRL_SLEEP:
  965. case AT_DEVICE_CTRL_WAKEUP:
  966. case AT_DEVICE_CTRL_NET_CONN:
  967. case AT_DEVICE_CTRL_NET_DISCONN:
  968. case AT_DEVICE_CTRL_SET_WIFI_INFO:
  969. case AT_DEVICE_CTRL_GET_SIGNAL:
  970. case AT_DEVICE_CTRL_GET_GPS:
  971. case AT_DEVICE_CTRL_GET_VER:
  972. LOG_W("ml307 not support the control command(%d).", cmd);
  973. break;
  974. default:
  975. LOG_E("input error control command(%d).", cmd);
  976. break;
  977. }
  978. return result;
  979. }
  980. const struct at_device_ops ml307_device_ops =
  981. {
  982. ml307_init,
  983. ml307_deinit,
  984. ml307_control,
  985. };
  986. static int ml307_device_class_register(void)
  987. {
  988. struct at_device_class *class = RT_NULL;
  989. class = (struct at_device_class *) rt_calloc(1, sizeof(struct at_device_class));
  990. if (class == RT_NULL)
  991. {
  992. LOG_E("no memory for ml307 device class create.");
  993. return -RT_ENOMEM;
  994. }
  995. /* fill ml307 device class object */
  996. #ifdef AT_USING_SOCKET
  997. ml307_socket_class_register(class);
  998. #endif
  999. class->device_ops = &ml307_device_ops;
  1000. return at_device_class_register(class, AT_DEVICE_CLASS_ML307);
  1001. }
  1002. INIT_DEVICE_EXPORT(ml307_device_class_register);
  1003. #endif /* AT_DEVICE_USING_ML307 */