at_device_bc28.c 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-02-12 luhuadong first version
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <at_device_bc28.h>
  13. #if !defined(AT_SW_VERSION_NUM) || AT_SW_VERSION_NUM < 0x10301
  14. #error "This AT Client version is older, please check and update latest AT Client!"
  15. #endif
  16. #define LOG_TAG "at.dev.bc28"
  17. #include <at_log.h>
  18. #ifdef AT_DEVICE_USING_BC28
  19. #define BC28_WAIT_CONNECT_TIME 5000
  20. #define BC28_THREAD_STACK_SIZE 2048
  21. #define BC28_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX/2)
  22. static int bc28_sleep(struct at_device *device)
  23. {
  24. return(RT_EOK);
  25. }
  26. static int bc28_wakeup(struct at_device *device)
  27. {
  28. return(RT_EOK);
  29. }
  30. static int bc28_reset(struct at_device *device)
  31. {
  32. struct at_device_bc28 *bc28 = (struct at_device_bc28 *)device->user_data;
  33. rt_pin_mode(bc28->power_pin, PIN_MODE_OUTPUT);
  34. rt_pin_write(bc28->power_pin, PIN_HIGH);
  35. rt_thread_mdelay(300);
  36. rt_pin_write(bc28->power_pin, PIN_LOW);
  37. bc28->power_status = 1;
  38. return(RT_EOK);
  39. }
  40. static int bc28_check_link_status(struct at_device *device)
  41. {
  42. at_response_t resp = RT_NULL;
  43. struct at_device_bc28 *bc28 = RT_NULL;
  44. int result = -RT_ERROR;
  45. bc28 = (struct at_device_bc28 *)device->user_data;
  46. if ( ! bc28->power_status) // power off
  47. {
  48. LOG_E("the power is off.");
  49. return(-RT_ERROR);
  50. }
  51. if (bc28->sleep_status) // is sleep status
  52. {
  53. if (bc28->power_pin != -1)
  54. {
  55. rt_pin_write(bc28->power_pin, PIN_HIGH);
  56. rt_thread_mdelay(100);
  57. rt_pin_write(bc28->power_pin, PIN_LOW);
  58. rt_thread_mdelay(200);
  59. }
  60. }
  61. resp = at_create_resp(64, 0, rt_tick_from_millisecond(300));
  62. if (resp == RT_NULL)
  63. {
  64. LOG_E("no memory for resp create.");
  65. return(-RT_ERROR);
  66. }
  67. result = -RT_ERROR;
  68. if (at_obj_exec_cmd(device->client, resp, "AT+CGATT?") == RT_EOK)
  69. {
  70. int link_stat = 0;
  71. if (at_resp_parse_line_args_by_kw(resp, "+CGATT:", "+CGATT:%d", &link_stat) > 0)
  72. {
  73. if (link_stat == 1)
  74. {
  75. result = RT_EOK;
  76. }
  77. }
  78. }
  79. at_delete_resp(resp);
  80. return(result);
  81. }
  82. /* ============================= bc28 network interface operations ============================= */
  83. /* set bc28 network interface device status and address information */
  84. static int bc28_netdev_set_info(struct netdev *netdev)
  85. {
  86. #define BC28_INFO_RESP_SIZE 128
  87. #define BC28_INFO_RESP_TIMOUT rt_tick_from_millisecond(5000)
  88. int result = RT_EOK;
  89. ip_addr_t addr;
  90. at_response_t resp = RT_NULL;
  91. struct at_device *device = RT_NULL;
  92. RT_ASSERT(netdev);
  93. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  94. if (device == RT_NULL)
  95. {
  96. LOG_E("get device(%s) failed.", netdev->name);
  97. return -RT_ERROR;
  98. }
  99. /* set network interface device status */
  100. netdev_low_level_set_status(netdev, RT_TRUE);
  101. netdev_low_level_set_link_status(netdev, RT_TRUE);
  102. netdev_low_level_set_dhcp_status(netdev, RT_TRUE);
  103. resp = at_create_resp(BC28_INFO_RESP_SIZE, 0, BC28_INFO_RESP_TIMOUT);
  104. if (resp == RT_NULL)
  105. {
  106. LOG_E("no memory for resp create.");
  107. result = -RT_ENOMEM;
  108. goto __exit;
  109. }
  110. /* set network interface device hardware address(IMEI) */
  111. {
  112. #define BC28_NETDEV_HWADDR_LEN 8
  113. #define BC28_IMEI_LEN 15
  114. char imei[BC28_IMEI_LEN] = {0};
  115. int i = 0, j = 0;
  116. /* send "AT+CGSN=1" commond to get device IMEI */
  117. if (at_obj_exec_cmd(device->client, resp, "AT+CGSN=1") != RT_EOK)
  118. {
  119. result = -RT_ERROR;
  120. goto __exit;
  121. }
  122. if (at_resp_parse_line_args(resp, 2, "+CGSN:%s", imei) <= 0)
  123. {
  124. LOG_E("%s device prase \"AT+CGSN=1\" cmd error.", device->name);
  125. result = -RT_ERROR;
  126. goto __exit;
  127. }
  128. LOG_D("%s device IMEI number: %s", device->name, imei);
  129. netdev->hwaddr_len = BC28_NETDEV_HWADDR_LEN;
  130. /* get hardware address by IMEI */
  131. for (i = 0, j = 0; i < BC28_NETDEV_HWADDR_LEN && j < BC28_IMEI_LEN; i++, j+=2)
  132. {
  133. if (j != BC28_IMEI_LEN - 1)
  134. {
  135. netdev->hwaddr[i] = (imei[j] - '0') * 10 + (imei[j + 1] - '0');
  136. }
  137. else
  138. {
  139. netdev->hwaddr[i] = (imei[j] - '0');
  140. }
  141. }
  142. }
  143. /* set network interface device IP address */
  144. {
  145. char ipaddr[IP_ADDR_SIZE_MAX] = {0};
  146. /* send "AT+CGPADDR" commond to get IP address */
  147. if (at_obj_exec_cmd(device->client, resp, "AT+CGPADDR") != RT_EOK)
  148. {
  149. result = -RT_ERROR;
  150. goto __exit;
  151. }
  152. /* parse response data "+CGPADDR: 0,<IP_address>" */
  153. if (at_resp_parse_line_args_by_kw(resp, "+CGPADDR:", "+CGPADDR:%*d,%s", ipaddr) <= 0)
  154. {
  155. LOG_E("%s device \"AT+CGPADDR\" cmd error.", device->name);
  156. result = -RT_ERROR;
  157. goto __exit;
  158. }
  159. LOG_D("%s device IP address: %s", device->name, ipaddr);
  160. /* set network interface address information */
  161. inet_aton(ipaddr, &addr);
  162. netdev_low_level_set_ipaddr(netdev, &addr);
  163. }
  164. /* set network interface device dns server */
  165. {
  166. #define DNS_ADDR_SIZE_MAX 16
  167. char dns_server1[DNS_ADDR_SIZE_MAX] = {0}, dns_server2[DNS_ADDR_SIZE_MAX] = {0};
  168. /* send "AT+QIDNSCFG?" commond to get DNS servers address */
  169. if (at_obj_exec_cmd(device->client, resp, "AT+QIDNSCFG?") != RT_EOK)
  170. {
  171. result = -RT_ERROR;
  172. goto __exit;
  173. }
  174. /* parse response data "PrimaryDns:<pri_dns>"
  175. * "SecondaryDns:<sec_dns>"
  176. */
  177. if (at_resp_parse_line_args_by_kw(resp, "PrimaryDns:", "PrimaryDns: %s", dns_server1) <= 0)
  178. {
  179. LOG_E("%s device prase \"AT+QIDNSCFG?\" cmd error.", device->name);
  180. result = -RT_ERROR;
  181. goto __exit;
  182. }
  183. if (at_resp_parse_line_args_by_kw(resp, "SecondaryDns:", "SecondaryDns: %s", dns_server2) <= 0)
  184. {
  185. LOG_E("%s device prase \"AT+QIDNSCFG?\" cmd error.", device->name);
  186. result = -RT_ERROR;
  187. goto __exit;
  188. }
  189. LOG_D("%s device primary DNS server address: %s", device->name, dns_server1);
  190. LOG_D("%s device secondary DNS server address: %s", device->name, dns_server2);
  191. inet_aton(dns_server1, &addr);
  192. netdev_low_level_set_dns_server(netdev, 0, &addr);
  193. inet_aton(dns_server2, &addr);
  194. netdev_low_level_set_dns_server(netdev, 1, &addr);
  195. }
  196. __exit:
  197. if (resp)
  198. {
  199. at_delete_resp(resp);
  200. }
  201. return result;
  202. }
  203. static void bc28_check_link_status_entry(void *parameter)
  204. {
  205. #define BC28_LINK_DELAY_TIME (60 * RT_TICK_PER_SECOND)
  206. rt_bool_t is_link_up;
  207. struct at_device *device = RT_NULL;
  208. struct netdev *netdev = (struct netdev *) parameter;
  209. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  210. if (device == RT_NULL)
  211. {
  212. LOG_E("get device(%s) failed.", netdev->name);
  213. return;
  214. }
  215. while (1)
  216. {
  217. is_link_up = (bc28_check_link_status(device) == RT_EOK);
  218. netdev_low_level_set_link_status(netdev, is_link_up);
  219. rt_thread_delay(BC28_LINK_DELAY_TIME);
  220. }
  221. }
  222. static int bc28_netdev_check_link_status(struct netdev *netdev)
  223. {
  224. #define BC28_LINK_THREAD_STACK_SIZE (1024 + 512)
  225. #define BC28_LINK_THREAD_PRIORITY (RT_THREAD_PRIORITY_MAX - 2)
  226. rt_thread_t tid;
  227. char tname[RT_NAME_MAX] = {0};
  228. RT_ASSERT(netdev);
  229. rt_snprintf(tname, RT_NAME_MAX, "%s", netdev->name);
  230. /* create bc28 link status polling thread */
  231. tid = rt_thread_create(tname, bc28_check_link_status_entry, (void *)netdev,
  232. BC28_LINK_THREAD_STACK_SIZE, BC28_LINK_THREAD_PRIORITY, 20);
  233. if (tid != RT_NULL)
  234. {
  235. rt_thread_startup(tid);
  236. }
  237. return RT_EOK;
  238. }
  239. static int bc28_net_init(struct at_device *device);
  240. static int bc28_netdev_set_up(struct netdev *netdev)
  241. {
  242. struct at_device *device = RT_NULL;
  243. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  244. if (device == RT_NULL)
  245. {
  246. LOG_E("get device(%s) failed.", netdev->name);
  247. return -RT_ERROR;
  248. }
  249. if (device->is_init == RT_FALSE)
  250. {
  251. bc28_net_init(device);
  252. device->is_init = RT_TRUE;
  253. netdev_low_level_set_status(netdev, RT_TRUE);
  254. LOG_D("network interface device(%s) set up status.", netdev->name);
  255. }
  256. return RT_EOK;
  257. }
  258. static int bc28_netdev_set_down(struct netdev *netdev)
  259. {
  260. struct at_device *device = RT_NULL;
  261. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  262. if (device == RT_NULL)
  263. {
  264. LOG_E("get device(%s) failed.", netdev->name);
  265. return -RT_ERROR;
  266. }
  267. if (device->is_init == RT_TRUE)
  268. {
  269. //bc28_power_off(device);
  270. device->is_init = RT_FALSE;
  271. netdev_low_level_set_status(netdev, RT_FALSE);
  272. LOG_D("network interface device(%s) set down status.", netdev->name);
  273. }
  274. return RT_EOK;
  275. }
  276. static int bc28_netdev_set_dns_server(struct netdev *netdev, uint8_t dns_num, ip_addr_t *dns_server)
  277. {
  278. #define BC28_DNS_RESP_LEN 64
  279. #define BC28_DNS_RESP_TIMEOUT rt_tick_from_millisecond(300)
  280. int result = RT_EOK;
  281. at_response_t resp = RT_NULL;
  282. struct at_device *device = RT_NULL;
  283. RT_ASSERT(netdev);
  284. RT_ASSERT(dns_server);
  285. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  286. if (device == RT_NULL)
  287. {
  288. LOG_E("get device(%s) failed.", netdev->name);
  289. return -RT_ERROR;
  290. }
  291. resp = at_create_resp(BC28_DNS_RESP_LEN, 0, BC28_DNS_RESP_TIMEOUT);
  292. if (resp == RT_NULL)
  293. {
  294. LOG_E("no memory for resp create.");
  295. result = -RT_ENOMEM;
  296. goto __exit;
  297. }
  298. if (at_obj_exec_cmd(device->client, resp, "AT+QIDNSCFG=%s", inet_ntoa(*dns_server)) != RT_EOK)
  299. {
  300. result = -RT_ERROR;
  301. goto __exit;
  302. }
  303. netdev_low_level_set_dns_server(netdev, dns_num, dns_server);
  304. __exit:
  305. if (resp)
  306. {
  307. at_delete_resp(resp);
  308. }
  309. return result;
  310. }
  311. #ifdef AT_USING_SOCKET
  312. int bc28_domain_resolve(const char *name, char ip[16]);
  313. #endif
  314. #ifdef NETDEV_USING_PING
  315. static int bc28_netdev_ping(struct netdev *netdev, const char *host,
  316. size_t data_len, uint32_t timeout, struct netdev_ping_resp *ping_resp)
  317. {
  318. #define BC28_PING_RESP_SIZE 128
  319. #define BC28_PING_IP_SIZE 16
  320. #define BC28_PING_TIMEOUT (10 * RT_TICK_PER_SECOND)
  321. rt_err_t result = RT_EOK;
  322. int response = -1, recv_data_len, ping_time, ttl;
  323. char ip_addr[BC28_PING_IP_SIZE] = {0};
  324. at_response_t resp = RT_NULL;
  325. struct at_device *device = RT_NULL;
  326. RT_ASSERT(netdev);
  327. RT_ASSERT(host);
  328. RT_ASSERT(ping_resp);
  329. device = at_device_get_by_name(AT_DEVICE_NAMETYPE_NETDEV, netdev->name);
  330. if (device == RT_NULL)
  331. {
  332. LOG_E("get device(%s) failed.", netdev->name);
  333. return -RT_ERROR;
  334. }
  335. resp = at_create_resp(BC28_PING_RESP_SIZE, 4, BC28_PING_TIMEOUT);
  336. if (resp == RT_NULL)
  337. {
  338. LOG_E("no memory for resp create");
  339. return -RT_ENOMEM;
  340. }
  341. /* DNS resolve */
  342. struct in_addr inp;
  343. if (inet_aton(host, &inp) > 0)
  344. {
  345. rt_strncpy(ip_addr, host, BC28_PING_IP_SIZE);
  346. }
  347. #ifdef AT_USING_SOCKET
  348. else
  349. {
  350. if(0 > bc28_domain_resolve(host, ip_addr))
  351. {
  352. LOG_E("can not resolve domain");
  353. goto __exit;
  354. }
  355. }
  356. #endif
  357. if (at_obj_exec_cmd(device->client, resp, "AT+NPING=%s,%d,%d",
  358. ip_addr, data_len, timeout*1000/RT_TICK_PER_SECOND) < 0)
  359. {
  360. result = -RT_ERROR;
  361. goto __exit;
  362. }
  363. if (at_resp_parse_line_args_by_kw(resp, "+NPINGERR:", "+NPINGERR:%d", &response) > 0)
  364. {
  365. switch (response)
  366. {
  367. case 1:
  368. result = -RT_ETIMEOUT;
  369. break;
  370. case 2:
  371. default:
  372. result = -RT_ERROR;
  373. break;
  374. }
  375. }
  376. else if (at_resp_parse_line_args_by_kw(resp, "+NPING:", "+NPING:%[^,],%d,%d",
  377. ip_addr, &ttl, &ping_time) > 0 )
  378. {
  379. inet_aton(ip_addr, &(ping_resp->ip_addr));
  380. ping_resp->data_len = data_len;
  381. ping_resp->ticks = rt_tick_from_millisecond(ping_time);
  382. ping_resp->ttl = ttl;
  383. result = RT_EOK;
  384. }
  385. else
  386. {
  387. result = -RT_ERROR;
  388. goto __exit;
  389. }
  390. __exit:
  391. if (resp)
  392. {
  393. at_delete_resp(resp);
  394. }
  395. return result;
  396. }
  397. #endif /* NETDEV_USING_PING */
  398. const struct netdev_ops bc28_netdev_ops =
  399. {
  400. bc28_netdev_set_up,
  401. bc28_netdev_set_down,
  402. RT_NULL,
  403. bc28_netdev_set_dns_server,
  404. RT_NULL,
  405. #ifdef NETDEV_USING_PING
  406. bc28_netdev_ping,
  407. #endif
  408. RT_NULL,
  409. };
  410. static struct netdev *bc28_netdev_add(const char *netdev_name)
  411. {
  412. #define ETHERNET_MTU 1500
  413. #define HWADDR_LEN 8
  414. struct netdev *netdev = RT_NULL;
  415. netdev = netdev_get_by_name(netdev_name);
  416. if (netdev != RT_NULL)
  417. {
  418. return (netdev);
  419. }
  420. netdev = (struct netdev *)rt_calloc(1, sizeof(struct netdev));
  421. if (netdev == RT_NULL)
  422. {
  423. LOG_E("no memory for netdev create.");
  424. return RT_NULL;
  425. }
  426. netdev->mtu = ETHERNET_MTU;
  427. netdev->ops = &bc28_netdev_ops;
  428. netdev->hwaddr_len = HWADDR_LEN;
  429. #ifdef SAL_USING_AT
  430. extern int sal_at_netdev_set_pf_info(struct netdev *netdev);
  431. /* set the network interface socket/netdb operations */
  432. sal_at_netdev_set_pf_info(netdev);
  433. #endif
  434. netdev_register(netdev, netdev_name, RT_NULL);
  435. return netdev;
  436. }
  437. /* ============================= bc28 device operations ============================= */
  438. /* initialize for bc28 */
  439. static void bc28_init_thread_entry(void *parameter)
  440. {
  441. #define INIT_RETRY 5
  442. #define CPIN_RETRY 5
  443. #define CSQ_RETRY 20
  444. #define CGREG_RETRY 50
  445. #define IPADDR_RETRY 10
  446. #define AT_DEFAULT_TIMEOUT 5000
  447. int i;
  448. int retry_num = INIT_RETRY;
  449. rt_err_t result = RT_EOK;
  450. at_response_t resp = RT_NULL;
  451. struct at_device *device = (struct at_device *) parameter;
  452. struct at_client *client = device->client;
  453. resp = at_create_resp(128, 0, rt_tick_from_millisecond(AT_DEFAULT_TIMEOUT));
  454. if (resp == RT_NULL)
  455. {
  456. LOG_E("no memory for resp create.");
  457. return;
  458. }
  459. LOG_D("start init %s device.", device->name);
  460. while (retry_num--)
  461. {
  462. /* reset the bc28 device */
  463. bc28_reset(device);
  464. rt_thread_mdelay(1000);
  465. /* wait bc28 startup finish, send AT every 500ms, if receive OK, SYNC success*/
  466. if (at_client_obj_wait_connect(client, BC28_WAIT_CONNECT_TIME))
  467. {
  468. result = -RT_ETIMEOUT;
  469. goto __exit;
  470. }
  471. /* disable echo */
  472. if (at_obj_exec_cmd(device->client, resp, "ATE0") != RT_EOK)
  473. {
  474. result = -RT_ERROR;
  475. LOG_E("ATE0");
  476. goto __exit;
  477. }
  478. /* disable auto register */
  479. if (at_obj_exec_cmd(device->client, resp, "AT+QREGSWT=2") != RT_EOK)
  480. {
  481. result = -RT_ERROR;
  482. LOG_E(">> AT+QREGSWT=2");
  483. goto __exit;
  484. }
  485. /* disable auto connect */
  486. if (at_obj_exec_cmd(device->client, resp, "AT+NCONFIG=AUTOCONNECT,FALSE") != RT_EOK)
  487. {
  488. result = -RT_ERROR;
  489. LOG_E(">> AT+NCONFIG=AUTOCONNECT,FALSE");
  490. goto __exit;
  491. }
  492. /* reboot */
  493. at_obj_exec_cmd(device->client, resp, "AT+NRB");
  494. rt_thread_mdelay(5000);
  495. while (at_obj_exec_cmd(device->client, resp, "AT") != RT_EOK)
  496. {
  497. rt_thread_mdelay(1000);
  498. }
  499. /* check IMEI */
  500. if (at_obj_exec_cmd(device->client, resp, "AT+CGSN=1") != RT_EOK)
  501. {
  502. result = -RT_ERROR;
  503. LOG_E(">> AT+CGSN=1");
  504. goto __exit;
  505. }
  506. /* search band */
  507. if (at_obj_exec_cmd(device->client, resp, "AT+NBAND=%d", AT_DEVICE_BC28_OP_BAND) != RT_EOK)
  508. {
  509. result = -RT_ERROR;
  510. LOG_E(">> AT+NBAND=8");
  511. goto __exit;
  512. }
  513. /* set max function */
  514. if (at_obj_exec_cmd(device->client, resp, "AT+CFUN=1") != RT_EOK)
  515. {
  516. result = -RT_ERROR;
  517. LOG_E(">> AT+CFUN=1");
  518. goto __exit;
  519. }
  520. /* auto report recv from tcp */
  521. if (at_obj_exec_cmd(device->client, resp, "AT+NSONMI=2") != RT_EOK)
  522. {
  523. result = -RT_ERROR;
  524. LOG_E(">> AT+NSONMI=2");
  525. goto __exit;
  526. }
  527. /* disable eDRX mode */
  528. if (at_obj_exec_cmd(device->client, resp, "AT+CEDRXS=0,5") != RT_EOK)
  529. {
  530. result = -RT_ERROR;
  531. LOG_E(">> AT+CEDRXS=0,5");
  532. goto __exit;
  533. }
  534. /* disable PSM mode */
  535. if (at_obj_exec_cmd(device->client, resp, "AT+CPSMS=0") != RT_EOK)
  536. {
  537. result = -RT_ERROR;
  538. LOG_E(">> AT+CPSMS=0");
  539. goto __exit;
  540. }
  541. /* check IMSI */
  542. if (at_obj_exec_cmd(device->client, resp, "AT+CIMI") != RT_EOK)
  543. {
  544. result = -RT_ERROR;
  545. LOG_E(">> AT+CIMI");
  546. goto __exit;
  547. }
  548. /* attach */
  549. if (at_obj_exec_cmd(device->client, resp, "AT+CGATT=1") != RT_EOK)
  550. {
  551. result = -RT_ERROR;
  552. LOG_E(">> AT+CGATT=1");
  553. goto __exit;
  554. }
  555. /* Get the baudrate */
  556. if (at_obj_exec_cmd(device->client, resp, "AT+NATSPEED?") != RT_EOK)
  557. {
  558. result = -RT_ERROR;
  559. LOG_E(">> AT+NATSPEED?");
  560. goto __exit;
  561. }
  562. at_resp_parse_line_args_by_kw(resp, "+NATSPEED:", "+NATSPEED:%d", &i);
  563. LOG_D("%s device baudrate %d", device->name, i);
  564. /* get module version */
  565. if (at_obj_exec_cmd(device->client, resp, "ATI") != RT_EOK)
  566. {
  567. result = -RT_ERROR;
  568. LOG_E(">> ATI");
  569. goto __exit;
  570. }
  571. for (i = 0; i < (int) resp->line_counts - 1; i++)
  572. {
  573. LOG_D("%s", at_resp_get_line(resp, i + 1));
  574. }
  575. /* check SIM card */
  576. for (i = 0; i < CPIN_RETRY; i++)
  577. {
  578. rt_thread_mdelay(1000);
  579. if (at_obj_exec_cmd(device->client, resp, "AT+CPIN?") == RT_EOK)
  580. {
  581. if (at_resp_get_line_by_kw(resp, "READY") != RT_NULL)
  582. break;
  583. }
  584. }
  585. if (i == CPIN_RETRY)
  586. {
  587. LOG_E("%s device SIM card detection failed.", device->name);
  588. result = -RT_ERROR;
  589. goto __exit;
  590. }
  591. /* check signal strength */
  592. for (i = 0; i < CSQ_RETRY; i++)
  593. {
  594. rt_thread_mdelay(1000);
  595. if (at_obj_exec_cmd(device->client, resp, "AT+CSQ") == RT_EOK)
  596. {
  597. int signal_strength = 0, err_rate = 0;
  598. if (at_resp_parse_line_args_by_kw(resp, "+CSQ:", "+CSQ:%d,%d", &signal_strength, &err_rate) > 0)
  599. {
  600. if ((signal_strength != 99) && (signal_strength != 0))
  601. {
  602. LOG_D("%s device signal strength: %d, channel bit error rate: %d",
  603. device->name, signal_strength, err_rate);
  604. break;
  605. }
  606. }
  607. }
  608. }
  609. if (i == CSQ_RETRY)
  610. {
  611. LOG_E("%s device signal strength check failed", device->name);
  612. result = -RT_ERROR;
  613. goto __exit;
  614. }
  615. /* check the GPRS network is registered */
  616. for (i = 0; i < CGREG_RETRY; i++)
  617. {
  618. rt_thread_mdelay(1000);
  619. if (at_obj_exec_cmd(device->client, resp, "AT+CGATT?") == RT_EOK)
  620. {
  621. int link_stat = 0;
  622. if (at_resp_parse_line_args_by_kw(resp, "+CGATT:", "+CGATT:%d", &link_stat) > 0)
  623. {
  624. if (link_stat == 1)
  625. {
  626. LOG_D("%s device GPRS is registered", device->name);
  627. break;
  628. }
  629. }
  630. }
  631. }
  632. if (i == CGREG_RETRY)
  633. {
  634. LOG_E("%s device GPRS is register failed", device->name);
  635. result = -RT_ERROR;
  636. goto __exit;
  637. }
  638. /* check the GPRS network IP address */
  639. for (i = 0; i < IPADDR_RETRY; i++)
  640. {
  641. rt_thread_mdelay(1000);
  642. if (at_obj_exec_cmd(device->client, resp, "AT+CGPADDR") == RT_EOK)
  643. {
  644. char ipaddr[IP_ADDR_SIZE_MAX] = {0};
  645. /* parse response data "+CGPADDR: 0,<IP_address>" */
  646. if (at_resp_parse_line_args_by_kw(resp, "+CGPADDR:", "+CGPADDR:%*d,%s", ipaddr) > 0)
  647. {
  648. LOG_D("%s device IP address: %s", device->name, ipaddr);
  649. break;
  650. }
  651. }
  652. }
  653. if (i == IPADDR_RETRY)
  654. {
  655. LOG_E("%s device GPRS is get IP address failed", device->name);
  656. result = -RT_ERROR;
  657. goto __exit;
  658. }
  659. /* initialize successfully */
  660. result = RT_EOK;
  661. break;
  662. __exit:
  663. if (result != RT_EOK)
  664. {
  665. /* power off the bc28 device */
  666. //bc28_power_off(device);
  667. rt_thread_mdelay(1000);
  668. LOG_I("%s device initialize retry...", device->name);
  669. }
  670. }
  671. if (resp)
  672. {
  673. at_delete_resp(resp);
  674. }
  675. if (result == RT_EOK)
  676. {
  677. /* set network interface device status and address information */
  678. bc28_netdev_set_info(device->netdev);
  679. /* check and create link staus sync thread */
  680. if (rt_thread_find(device->netdev->name) == RT_NULL)
  681. {
  682. bc28_netdev_check_link_status(device->netdev);
  683. }
  684. LOG_I("%s device network initialize success.", device->name);
  685. }
  686. else
  687. {
  688. LOG_E("%s device network initialize failed(%d).", device->name, result);
  689. }
  690. }
  691. /* bc28 device network initialize */
  692. static int bc28_net_init(struct at_device *device)
  693. {
  694. #ifdef AT_DEVICE_BC28_INIT_ASYN
  695. rt_thread_t tid;
  696. tid = rt_thread_create("bc28_net", bc28_init_thread_entry, (void *)device,
  697. BC28_THREAD_STACK_SIZE, BC28_THREAD_PRIORITY, 20);
  698. if (tid)
  699. {
  700. rt_thread_startup(tid);
  701. }
  702. else
  703. {
  704. LOG_E("create %s device init thread failed.", device->name);
  705. return -RT_ERROR;
  706. }
  707. #else
  708. bc28_init_thread_entry(device);
  709. #endif /* AT_DEVICE_BC28_INIT_ASYN */
  710. return RT_EOK;
  711. }
  712. static int bc28_init(struct at_device *device)
  713. {
  714. struct at_device_bc28 *bc28 = (struct at_device_bc28 *)device->user_data;
  715. /* configure AT client */
  716. rt_device_t serial = rt_device_find(bc28->client_name);
  717. struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT;
  718. config.baud_rate = BC28_AT_CLIENT_BAUD_RATE;
  719. config.data_bits = DATA_BITS_8;
  720. config.stop_bits = STOP_BITS_1;
  721. config.bufsz = bc28->recv_bufsz;
  722. config.parity = PARITY_NONE;
  723. rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config);
  724. rt_device_close(serial);
  725. /* initialize AT client */
  726. at_client_init(bc28->client_name, bc28->recv_bufsz);
  727. device->client = at_client_get(bc28->client_name);
  728. if (device->client == RT_NULL)
  729. {
  730. LOG_E("get AT client(%s) failed.", bc28->client_name);
  731. return -RT_ERROR;
  732. }
  733. /* register URC data execution function */
  734. #ifdef AT_USING_SOCKET
  735. bc28_socket_init(device);
  736. #endif
  737. /* add bc28 device to the netdev list */
  738. device->netdev = bc28_netdev_add(bc28->device_name);
  739. if (device->netdev == RT_NULL)
  740. {
  741. LOG_E("add netdev(%s) failed.", bc28->device_name);
  742. return -RT_ERROR;
  743. }
  744. /* initialize bc28 pin configuration */
  745. if (bc28->power_pin != -1)
  746. {
  747. rt_pin_mode(bc28->power_pin, PIN_MODE_OUTPUT);
  748. rt_pin_write(bc28->power_pin, PIN_LOW);
  749. }
  750. /* initialize bc28 device network */
  751. return bc28_netdev_set_up(device->netdev);
  752. }
  753. static int bc28_deinit(struct at_device *device)
  754. {
  755. RT_ASSERT(device);
  756. return bc28_netdev_set_down(device->netdev);
  757. }
  758. static int bc28_control(struct at_device *device, int cmd, void *arg)
  759. {
  760. int result = -RT_ERROR;
  761. RT_ASSERT(device);
  762. switch (cmd)
  763. {
  764. case AT_DEVICE_CTRL_RESET:
  765. result = bc28_reset(device);
  766. break;
  767. case AT_DEVICE_CTRL_SLEEP:
  768. case AT_DEVICE_CTRL_WAKEUP:
  769. case AT_DEVICE_CTRL_POWER_ON:
  770. case AT_DEVICE_CTRL_POWER_OFF:
  771. case AT_DEVICE_CTRL_LOW_POWER:
  772. case AT_DEVICE_CTRL_NET_CONN:
  773. case AT_DEVICE_CTRL_NET_DISCONN:
  774. case AT_DEVICE_CTRL_SET_WIFI_INFO:
  775. case AT_DEVICE_CTRL_GET_SIGNAL:
  776. case AT_DEVICE_CTRL_GET_GPS:
  777. case AT_DEVICE_CTRL_GET_VER:
  778. LOG_W("not support the control command(%d).", cmd);
  779. break;
  780. default:
  781. LOG_E("input error control command(%d).", cmd);
  782. break;
  783. }
  784. return result;
  785. }
  786. const struct at_device_ops bc28_device_ops =
  787. {
  788. bc28_init,
  789. bc28_deinit,
  790. bc28_control,
  791. };
  792. static int bc28_device_class_register(void)
  793. {
  794. struct at_device_class *class = RT_NULL;
  795. class = (struct at_device_class *) rt_calloc(1, sizeof(struct at_device_class));
  796. if (class == RT_NULL)
  797. {
  798. LOG_E("no memory for device class create.");
  799. return -RT_ENOMEM;
  800. }
  801. /* fill bc28 device class object */
  802. #ifdef AT_USING_SOCKET
  803. bc28_socket_class_register(class);
  804. #endif
  805. class->device_ops = &bc28_device_ops;
  806. return at_device_class_register(class, AT_DEVICE_CLASS_BC28);
  807. }
  808. INIT_DEVICE_EXPORT(bc28_device_class_register);
  809. #endif /* AT_DEVICE_USING_BC28 */