spi_wifi_rw009.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /*
  2. * File : spi_wifi_rw009.c
  3. * This file is part of RT-Thread RTOS
  4. * Copyright by Shanghai Real-Thread Electronic Technology Co.,Ltd
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2014-07-31 aozima the first version
  23. * 2014-09-18 aozima update command & response.
  24. */
  25. #include <rtthread.h>
  26. #include <drivers/spi.h>
  27. #include <netif/ethernetif.h>
  28. #include <netif/etharp.h>
  29. #include <lwip/icmp.h>
  30. #include "lwipopts.h"
  31. #define WIFI_DEBUG_ON
  32. // #define ETH_RX_DUMP
  33. // #define ETH_TX_DUMP
  34. #ifdef WIFI_DEBUG_ON
  35. #define WIFI_DEBUG rt_kprintf("[RW009] ");rt_kprintf
  36. //#define SPI_DEBUG rt_kprintf("[SPI] ");rt_kprintf
  37. #define SPI_DEBUG(...)
  38. #else
  39. #define WIFI_DEBUG(...)
  40. #define SPI_DEBUG(...)
  41. #endif /* #ifdef WIFI_DEBUG_ON */
  42. /********************************* RW009 **************************************/
  43. #include "spi_wifi_rw009.h"
  44. /* tools */
  45. #define node_entry(node, type, member) \
  46. ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member)))
  47. #define member_offset(type, member) \
  48. ((unsigned long)(&((type *)0)->member))
  49. #define MAX_SPI_PACKET_SIZE (member_offset(struct spi_data_packet, buffer) + SPI_MAX_DATA_LEN)
  50. #define MAX_SPI_BUFFER_SIZE (sizeof(struct spi_response) + MAX_SPI_PACKET_SIZE)
  51. #define MAX_ADDR_LEN 6
  52. struct rw009_wifi
  53. {
  54. /* inherit from ethernet device */
  55. struct eth_device parent;
  56. struct rt_spi_device *rt_spi_device;
  57. /* interface address info. */
  58. rt_uint8_t dev_addr[MAX_ADDR_LEN]; /* hw address */
  59. rt_uint8_t active;
  60. struct rt_mempool spi_tx_mp;
  61. struct rt_mempool spi_rx_mp;
  62. struct rt_mailbox spi_tx_mb;
  63. struct rt_mailbox eth_rx_mb;
  64. int spi_tx_mb_pool[SPI_TX_POOL_SIZE + 1];
  65. int eth_rx_mb_pool[SPI_RX_POOL_SIZE + 1];
  66. int rw009_cmd_mb_pool[3];
  67. struct rt_mailbox rw009_cmd_mb;
  68. uint32_t last_cmd;
  69. ALIGN(4)
  70. rt_uint8_t spi_tx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_TX_POOL_SIZE];
  71. ALIGN(4)
  72. rt_uint8_t spi_rx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_RX_POOL_SIZE];
  73. ALIGN(4)
  74. uint8_t spi_hw_rx_buffer[MAX_SPI_BUFFER_SIZE];
  75. /* status for RW009 */
  76. rw009_ap_info ap_info; /* AP info for conn. */
  77. rw009_ap_info *ap_scan; /* AP list for SCAN. */
  78. uint32_t ap_scan_count;
  79. };
  80. static struct rw009_wifi rw009_wifi_device;
  81. static struct rt_event spi_wifi_data_event;
  82. static void resp_handler(struct rw009_wifi *wifi_device, struct rw009_resp *resp)
  83. {
  84. struct rw009_resp *resp_return = RT_NULL;
  85. switch (resp->cmd)
  86. {
  87. case RW009_CMD_INIT:
  88. WIFI_DEBUG("resp_handler RW009_CMD_INIT\n");
  89. resp_return = (struct rw009_resp *)rt_malloc(member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_init)); //TODO:
  90. if(resp_return == RT_NULL) break;
  91. memcpy(resp_return, resp, member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_init));
  92. WIFI_DEBUG("sn:%-*.*s\n", sizeof(resp->resp.init.sn), sizeof(resp->resp.init.sn), resp->resp.init.sn);
  93. WIFI_DEBUG("version:%-*.*s\n", sizeof(resp->resp.init.version), sizeof(resp->resp.init.version), resp->resp.init.version);
  94. rt_memcpy(wifi_device->dev_addr, resp->resp.init.mac, 6);
  95. break;
  96. case RW009_CMD_SCAN:
  97. if( resp->len == sizeof(rw009_ap_info) )
  98. {
  99. rw009_ap_info *ap_scan = rt_realloc(wifi_device->ap_scan, sizeof(rw009_ap_info) * (wifi_device->ap_scan_count + 1) );
  100. if(ap_scan != RT_NULL)
  101. {
  102. memcpy( &ap_scan[wifi_device->ap_scan_count], &resp->resp.ap_info, sizeof(rw009_ap_info) );
  103. //dump
  104. if(1)
  105. {
  106. #ifdef WIFI_DEBUG_ON
  107. rw009_ap_info *ap_info = &resp->resp.ap_info;
  108. WIFI_DEBUG("SCAN SSID:%-32.32s\n", ap_info->ssid);
  109. WIFI_DEBUG("SCAN BSSID:%02X-%02X-%02X-%02X-%02X-%02X\n",
  110. ap_info->bssid[0],
  111. ap_info->bssid[1],
  112. ap_info->bssid[2],
  113. ap_info->bssid[3],
  114. ap_info->bssid[4],
  115. ap_info->bssid[5]);
  116. WIFI_DEBUG("SCAN rssi:%ddBm\n", ap_info->rssi);
  117. WIFI_DEBUG("SCAN rate:%dMbps\n", ap_info->max_data_rate/1000);
  118. WIFI_DEBUG("SCAN channel:%d\n", ap_info->channel);
  119. WIFI_DEBUG("SCAN security:%08X\n\n", ap_info->security);
  120. #endif /* WIFI_DEBUG_ON */
  121. }
  122. wifi_device->ap_scan_count++;
  123. wifi_device->ap_scan = ap_scan;
  124. }
  125. return; /* wait for next ap */
  126. }
  127. break;
  128. case RW009_CMD_JOIN:
  129. case RW009_CMD_EASY_JOIN:
  130. WIFI_DEBUG("resp_handler RW009_CMD_EASY_JOIN\n");
  131. resp_return = (struct rw009_resp *)rt_malloc(member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_join)); //TODO:
  132. if(resp_return == RT_NULL) break;
  133. memcpy(resp_return, resp, member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_join));
  134. if( resp->result == 0 )
  135. {
  136. memcpy(&wifi_device->ap_info, &resp_return->resp.ap_info, sizeof(rw009_resp_join));
  137. wifi_device->active = 1;
  138. eth_device_linkchange(&wifi_device->parent, RT_TRUE);
  139. }
  140. else
  141. {
  142. WIFI_DEBUG("RW009_CMD_EASY_JOIN result: %d\n", resp->result );
  143. }
  144. //dupm
  145. if(1)
  146. {
  147. #ifdef WIFI_DEBUG_ON
  148. rw009_ap_info *ap_info = &resp->resp.ap_info;
  149. WIFI_DEBUG("JOIN SSID:%-32.32s\n", ap_info->ssid);
  150. WIFI_DEBUG("JOIN BSSID:%02X-%02X-%02X-%02X-%02X-%02X\n",
  151. ap_info->bssid[0],
  152. ap_info->bssid[1],
  153. ap_info->bssid[2],
  154. ap_info->bssid[3],
  155. ap_info->bssid[4],
  156. ap_info->bssid[5]);
  157. WIFI_DEBUG("JOIN rssi:%ddBm\n", ap_info->rssi);
  158. WIFI_DEBUG("JOIN rate:%dMbps\n", ap_info->max_data_rate/1000);
  159. WIFI_DEBUG("JOIN channel:%d\n", ap_info->channel);
  160. WIFI_DEBUG("JOIN security:%08X\n\n", ap_info->security);
  161. #endif /* WIFI_DEBUG_ON */
  162. }
  163. break;
  164. case RW009_CMD_RSSI:
  165. // TODO: client RSSI.
  166. {
  167. rw009_ap_info *ap_info = &resp->resp.ap_info;
  168. wifi_device->ap_info.rssi = ap_info->rssi;
  169. WIFI_DEBUG("current RSSI: %d\n", wifi_device->ap_info.rssi);
  170. }
  171. break;
  172. case RW009_CMD_SOFTAP:
  173. {
  174. if( resp->result == 0 )
  175. {
  176. ;
  177. wifi_device->active = 1;
  178. eth_device_linkchange(&wifi_device->parent, RT_TRUE);
  179. }
  180. else
  181. {
  182. WIFI_DEBUG("RW009_CMD_EASY_JOIN result: %d\n", resp->result );
  183. }
  184. }
  185. break;
  186. default:
  187. WIFI_DEBUG("resp_handler %d\n", resp->cmd);
  188. break;
  189. }
  190. if(resp->cmd == wifi_device->last_cmd)
  191. {
  192. rt_mb_send(&wifi_device->rw009_cmd_mb, (rt_uint32_t)resp_return);
  193. return;
  194. }
  195. else
  196. {
  197. rt_free(resp_return);
  198. }
  199. }
  200. static rt_err_t rw009_cmd(struct rw009_wifi *wifi_device, uint32_t cmd, void *args)
  201. {
  202. rt_err_t result = RT_EOK;
  203. rt_int32_t timeout = RW009_CMD_TIMEOUT;
  204. struct spi_data_packet *data_packet;
  205. struct rw009_cmd *wifi_cmd = RT_NULL;
  206. struct rw009_resp *resp = RT_NULL;
  207. wifi_device->last_cmd = cmd;
  208. data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
  209. wifi_cmd = (struct rw009_cmd *)data_packet->buffer;
  210. wifi_cmd->cmd = cmd;
  211. wifi_cmd->len = 0;
  212. if( cmd == RW009_CMD_INIT )
  213. {
  214. wifi_cmd->len = sizeof(rw009_cmd_init);
  215. }
  216. else if( cmd == RW009_CMD_SCAN )
  217. {
  218. wifi_cmd->len = 0;
  219. timeout += RT_TICK_PER_SECOND*10;
  220. if(wifi_device->ap_scan)
  221. {
  222. rt_free(wifi_device->ap_scan);
  223. wifi_device->ap_scan = RT_NULL;
  224. wifi_device->ap_scan_count = 0;
  225. }
  226. }
  227. else if( cmd == RW009_CMD_JOIN )
  228. {
  229. wifi_cmd->len = sizeof(rw009_cmd_join);
  230. }
  231. else if( cmd == RW009_CMD_EASY_JOIN )
  232. {
  233. wifi_cmd->len = sizeof(rw009_cmd_easy_join);
  234. timeout += RT_TICK_PER_SECOND*5;
  235. }
  236. else if( cmd == RW009_CMD_RSSI )
  237. {
  238. wifi_cmd->len = sizeof(rw009_cmd_rssi);
  239. }
  240. else if( cmd == RW009_CMD_SOFTAP )
  241. {
  242. wifi_cmd->len = sizeof(rw009_cmd_softap);
  243. }
  244. else
  245. {
  246. WIFI_DEBUG("unkown RW009 CMD %d\n", cmd);
  247. result = -RT_ENOSYS;
  248. rt_mp_free(data_packet);
  249. data_packet = RT_NULL;
  250. }
  251. if(data_packet == RT_NULL)
  252. {
  253. goto _exit;
  254. }
  255. if(wifi_cmd->len)
  256. memcpy(&wifi_cmd->params, args, wifi_cmd->len);
  257. data_packet->data_type = data_type_cmd;
  258. data_packet->data_len = member_offset(struct rw009_cmd, params) + wifi_cmd->len;
  259. rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
  260. rt_event_send(&spi_wifi_data_event, 1);
  261. result = rt_mb_recv(&wifi_device->rw009_cmd_mb,
  262. (rt_uint32_t *)&resp,
  263. timeout);
  264. if ( result != RT_EOK )
  265. {
  266. WIFI_DEBUG("CMD %d error, resultL %d\n", cmd, result );
  267. }
  268. if(resp != RT_NULL)
  269. result = resp->result;
  270. _exit:
  271. wifi_device->last_cmd = 0;
  272. if(resp) rt_free(resp);
  273. return result;
  274. }
  275. static rt_err_t spi_wifi_transfer(struct rw009_wifi *dev)
  276. {
  277. struct pbuf *p = RT_NULL;
  278. struct spi_cmd_request cmd;
  279. struct spi_response resp;
  280. rt_err_t result;
  281. const struct spi_data_packet *data_packet = RT_NULL;
  282. struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev;
  283. struct rt_spi_device *rt_spi_device = wifi_device->rt_spi_device;
  284. spi_wifi_int_cmd(0);
  285. while (spi_wifi_is_busy());
  286. SPI_DEBUG("sequence start!\n");
  287. memset(&cmd, 0, sizeof(struct spi_cmd_request));
  288. cmd.magic1 = CMD_MAGIC1;
  289. cmd.magic2 = CMD_MAGIC2;
  290. cmd.flag |= CMD_FLAG_MRDY;
  291. result = rt_mb_recv(&wifi_device->spi_tx_mb,
  292. (rt_uint32_t *)&data_packet,
  293. 0);
  294. if ((result == RT_EOK) && (data_packet != RT_NULL) && (data_packet->data_len > 0))
  295. {
  296. cmd.M2S_len = data_packet->data_len + member_offset(struct spi_data_packet, buffer);
  297. //SPI_DEBUG("cmd.M2S_len = %d\n", cmd.M2S_len);
  298. }
  299. rt_spi_send(rt_spi_device, &cmd, sizeof(cmd));
  300. while (spi_wifi_is_busy());
  301. {
  302. struct rt_spi_message message;
  303. uint32_t max_data_len = 0;
  304. /* setup message */
  305. message.send_buf = RT_NULL;
  306. message.recv_buf = &resp;
  307. message.length = sizeof(resp);
  308. message.cs_take = 1;
  309. message.cs_release = 0;
  310. rt_spi_take_bus(rt_spi_device);
  311. /* transfer message */
  312. rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
  313. if ((resp.magic1 != RESP_MAGIC1) || (resp.magic2 != RESP_MAGIC2))
  314. {
  315. SPI_DEBUG("bad resp magic, abort!\n");
  316. goto _bad_resp_magic;
  317. }
  318. if (resp.flag & RESP_FLAG_SRDY)
  319. {
  320. SPI_DEBUG("RESP_FLAG_SRDY\n");
  321. max_data_len = cmd.M2S_len;
  322. }
  323. if (resp.S2M_len)
  324. {
  325. SPI_DEBUG("resp.S2M_len: %d\n", resp.S2M_len);
  326. if (resp.S2M_len > MAX_SPI_PACKET_SIZE)
  327. {
  328. SPI_DEBUG("resp.S2M_len %d > %d(MAX_SPI_PACKET_SIZE), drop!\n", resp.S2M_len, MAX_SPI_PACKET_SIZE);
  329. resp.S2M_len = 0;//drop
  330. }
  331. if (resp.S2M_len > max_data_len)
  332. max_data_len = resp.S2M_len;
  333. }
  334. if (max_data_len == 0)
  335. {
  336. SPI_DEBUG("no rx or tx data!\n");
  337. }
  338. //SPI_DEBUG("max_data_len = %d\n", max_data_len);
  339. _bad_resp_magic:
  340. /* setup message */
  341. message.send_buf = data_packet;//&tx_buffer;
  342. message.recv_buf = wifi_device->spi_hw_rx_buffer;//&rx_buffer;
  343. message.length = max_data_len;
  344. message.cs_take = 0;
  345. message.cs_release = 1;
  346. /* transfer message */
  347. rt_spi_device->bus->ops->xfer(rt_spi_device, &message);
  348. rt_spi_release_bus(rt_spi_device);
  349. if (cmd.M2S_len && (resp.flag & RESP_FLAG_SRDY))
  350. {
  351. rt_mp_free((void *)data_packet);
  352. }
  353. if ((resp.S2M_len) && (resp.S2M_len <= MAX_SPI_PACKET_SIZE))
  354. {
  355. data_packet = (struct spi_data_packet *)wifi_device->spi_hw_rx_buffer;
  356. if (data_packet->data_type == data_type_eth_data)
  357. {
  358. if (wifi_device->active)
  359. {
  360. p = pbuf_alloc(PBUF_LINK, data_packet->data_len, PBUF_RAM);
  361. pbuf_take(p, (rt_uint8_t *)data_packet->buffer, data_packet->data_len);
  362. rt_mb_send(&wifi_device->eth_rx_mb, (rt_uint32_t)p);
  363. eth_device_ready((struct eth_device *)dev);
  364. }
  365. else
  366. {
  367. SPI_DEBUG("!active, RX drop.\n");
  368. }
  369. }
  370. else if (data_packet->data_type == data_type_resp)
  371. {
  372. SPI_DEBUG("data_type_resp\n");
  373. resp_handler(dev, (struct rw009_resp *)data_packet->buffer);
  374. }
  375. else
  376. {
  377. SPI_DEBUG("data_type: %d, %dbyte\n",
  378. data_packet->data_type,
  379. data_packet->data_len);
  380. }
  381. }
  382. }
  383. spi_wifi_int_cmd(1);
  384. SPI_DEBUG("sequence finish!\n\n");
  385. if ((cmd.M2S_len == 0) && (resp.S2M_len == 0))
  386. {
  387. return -RT_ERROR;
  388. }
  389. return RT_EOK;
  390. }
  391. #if defined(ETH_RX_DUMP) || defined(ETH_TX_DUMP)
  392. static void packet_dump(const char *msg, const struct pbuf *p)
  393. {
  394. const struct pbuf* q;
  395. rt_uint32_t i,j;
  396. rt_uint8_t *ptr = p->payload;
  397. rt_kprintf("%s %d byte\n", msg, p->tot_len);
  398. i=0;
  399. for(q=p; q != RT_NULL; q= q->next)
  400. {
  401. ptr = q->payload;
  402. for(j=0; j<q->len; j++)
  403. {
  404. if( (i%8) == 0 )
  405. {
  406. rt_kprintf(" ");
  407. }
  408. if( (i%16) == 0 )
  409. {
  410. rt_kprintf("\r\n");
  411. }
  412. rt_kprintf("%02x ",*ptr);
  413. i++;
  414. ptr++;
  415. }
  416. }
  417. rt_kprintf("\n\n");
  418. }
  419. #endif /* dump */
  420. /********************************* RT-Thread Ethernet interface begin **************************************/
  421. static rt_err_t rw009_wifi_init(rt_device_t dev)
  422. {
  423. return RT_EOK;
  424. }
  425. static rt_err_t rw009_wifi_open(rt_device_t dev, rt_uint16_t oflag)
  426. {
  427. return RT_EOK;
  428. }
  429. static rt_err_t rw009_wifi_close(rt_device_t dev)
  430. {
  431. return RT_EOK;
  432. }
  433. static rt_size_t rw009_wifi_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  434. {
  435. rt_set_errno(-RT_ENOSYS);
  436. return 0;
  437. }
  438. static rt_size_t rw009_wifi_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  439. {
  440. rt_set_errno(-RT_ENOSYS);
  441. return 0;
  442. }
  443. static rt_err_t rw009_wifi_control(rt_device_t dev, rt_uint8_t cmd, void *args)
  444. {
  445. struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev;
  446. rt_err_t result = RT_EOK;
  447. if (cmd == NIOCTL_GADDR)
  448. {
  449. memcpy(args, wifi_device->dev_addr, 6);
  450. }
  451. else
  452. {
  453. result = rw009_cmd(wifi_device, cmd, args);
  454. }
  455. return result;
  456. }
  457. /* transmit packet. */
  458. rt_err_t rw009_wifi_tx(rt_device_t dev, struct pbuf *p)
  459. {
  460. rt_err_t result = RT_EOK;
  461. struct spi_data_packet *data_packet;
  462. struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev;
  463. if (!wifi_device->active)
  464. {
  465. WIFI_DEBUG("!active, TX drop!\n");
  466. return RT_EOK;
  467. }
  468. /* get free tx buffer */
  469. data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER);
  470. if (data_packet != RT_NULL)
  471. {
  472. data_packet->data_type = data_type_eth_data;
  473. data_packet->data_len = p->tot_len;
  474. pbuf_copy_partial(p, data_packet->buffer, data_packet->data_len, 0);
  475. rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet);
  476. rt_event_send(&spi_wifi_data_event, 1);
  477. }
  478. else
  479. return -RT_ERROR;
  480. #ifdef ETH_TX_DUMP
  481. packet_dump("TX dump", p);
  482. #endif /* ETH_TX_DUMP */
  483. /* Return SUCCESS */
  484. return result;
  485. }
  486. /* reception packet. */
  487. struct pbuf *rw009_wifi_rx(rt_device_t dev)
  488. {
  489. struct pbuf *p = RT_NULL;
  490. struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev;
  491. if (rt_mb_recv(&wifi_device->eth_rx_mb, (rt_uint32_t *)&p, 0) != RT_EOK)
  492. {
  493. return RT_NULL;
  494. }
  495. #ifdef ETH_RX_DUMP
  496. if(p)
  497. packet_dump("RX dump", p);
  498. #endif /* ETH_RX_DUMP */
  499. return p;
  500. }
  501. /********************************* RT-Thread Ethernet interface end **************************************/
  502. static void spi_wifi_data_thread_entry(void *parameter)
  503. {
  504. rt_uint32_t e;
  505. rt_err_t result;
  506. while (1)
  507. {
  508. /* receive first event */
  509. if (rt_event_recv(&spi_wifi_data_event,
  510. 1,
  511. RT_EVENT_FLAG_AND | RT_EVENT_FLAG_CLEAR,
  512. RT_WAITING_FOREVER,
  513. &e) != RT_EOK)
  514. {
  515. continue;
  516. }
  517. result = spi_wifi_transfer(&rw009_wifi_device);
  518. if (result == RT_EOK)
  519. {
  520. rt_event_send(&spi_wifi_data_event, 1);
  521. }
  522. }
  523. }
  524. rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode)
  525. {
  526. /* align and struct size check. */
  527. RT_ASSERT( (SPI_MAX_DATA_LEN & 0x03) == 0);
  528. RT_ASSERT( sizeof(struct rw009_resp) <= SPI_MAX_DATA_LEN);
  529. memset(&rw009_wifi_device, 0, sizeof(struct rw009_wifi));
  530. rw009_wifi_device.rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
  531. if (rw009_wifi_device.rt_spi_device == RT_NULL)
  532. {
  533. SPI_DEBUG("spi device %s not found!\r\n", spi_device_name);
  534. return -RT_ENOSYS;
  535. }
  536. /* config spi */
  537. {
  538. struct rt_spi_configuration cfg;
  539. cfg.data_width = 8;
  540. cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0. */
  541. cfg.max_hz = 15 * 1000000; /* 10M */
  542. rt_spi_configure(rw009_wifi_device.rt_spi_device, &cfg);
  543. }
  544. rw009_wifi_device.parent.parent.init = rw009_wifi_init;
  545. rw009_wifi_device.parent.parent.open = rw009_wifi_open;
  546. rw009_wifi_device.parent.parent.close = rw009_wifi_close;
  547. rw009_wifi_device.parent.parent.read = rw009_wifi_read;
  548. rw009_wifi_device.parent.parent.write = rw009_wifi_write;
  549. rw009_wifi_device.parent.parent.control = rw009_wifi_control;
  550. rw009_wifi_device.parent.parent.user_data = RT_NULL;
  551. rw009_wifi_device.parent.eth_rx = rw009_wifi_rx;
  552. rw009_wifi_device.parent.eth_tx = rw009_wifi_tx;
  553. rt_mp_init(&rw009_wifi_device.spi_tx_mp,
  554. "spi_tx",
  555. &rw009_wifi_device.spi_tx_mempool[0],
  556. sizeof(rw009_wifi_device.spi_tx_mempool),
  557. sizeof(struct spi_data_packet));
  558. rt_mp_init(&rw009_wifi_device.spi_rx_mp,
  559. "spi_rx",
  560. &rw009_wifi_device.spi_rx_mempool[0],
  561. sizeof(rw009_wifi_device.spi_rx_mempool),
  562. sizeof(struct spi_data_packet));
  563. rt_mb_init(&rw009_wifi_device.spi_tx_mb,
  564. "spi_tx",
  565. &rw009_wifi_device.spi_tx_mb_pool[0],
  566. SPI_TX_POOL_SIZE,
  567. RT_IPC_FLAG_PRIO);
  568. rt_mb_init(&rw009_wifi_device.eth_rx_mb,
  569. "eth_rx",
  570. &rw009_wifi_device.eth_rx_mb_pool[0],
  571. SPI_TX_POOL_SIZE,
  572. RT_IPC_FLAG_PRIO);
  573. rt_mb_init(&rw009_wifi_device.rw009_cmd_mb,
  574. "wifi_cmd",
  575. &rw009_wifi_device.rw009_cmd_mb_pool[0],
  576. sizeof(rw009_wifi_device.rw009_cmd_mb_pool) / 4,
  577. RT_IPC_FLAG_PRIO);
  578. rt_event_init(&spi_wifi_data_event, "wifi", RT_IPC_FLAG_FIFO);
  579. spi_wifi_hw_init();
  580. {
  581. rt_thread_t tid;
  582. tid = rt_thread_create("wifi",
  583. spi_wifi_data_thread_entry,
  584. RT_NULL,
  585. 2048,
  586. RT_THREAD_PRIORITY_MAX - 2,
  587. 20);
  588. if (tid != RT_NULL)
  589. rt_thread_startup(tid);
  590. }
  591. /* init: get mac address */
  592. {
  593. rw009_cmd_init init;
  594. init.mode = mode;
  595. WIFI_DEBUG("wifi_control RW009_CMD_INIT\n");
  596. rw009_wifi_control((rt_device_t)&rw009_wifi_device,
  597. RW009_CMD_INIT,
  598. (void *)&init); // 0: firmware, 1: STA, 2:AP
  599. }
  600. /* register eth device */
  601. eth_device_init(&(rw009_wifi_device.parent), "w0");
  602. eth_device_linkchange(&rw009_wifi_device.parent, RT_FALSE);
  603. return RT_EOK;
  604. }
  605. void spi_wifi_isr(int vector)
  606. {
  607. /* enter interrupt */
  608. rt_interrupt_enter();
  609. SPI_DEBUG("spi_wifi_isr\n");
  610. rt_event_send(&spi_wifi_data_event, 1);
  611. /* leave interrupt */
  612. rt_interrupt_leave();
  613. }
  614. /********************************* RW009 tools **************************************/
  615. rt_err_t rw009_join(const char * SSID, const char * passwd)
  616. {
  617. rt_err_t result;
  618. rt_device_t wifi_device;
  619. rw009_cmd_easy_join easy_join;
  620. wifi_device = rt_device_find("w0");
  621. if(wifi_device == RT_NULL)
  622. return -RT_ENOSYS;
  623. strncpy( easy_join.ssid, SSID, sizeof(easy_join.ssid) );
  624. strncpy( easy_join.passwd, passwd, sizeof(easy_join.passwd) );
  625. result = rt_device_control(wifi_device,
  626. RW009_CMD_EASY_JOIN,
  627. (void *)&easy_join);
  628. return result;
  629. }
  630. rt_err_t rw009_softap(const char * SSID, const char * passwd,uint32_t security,uint32_t channel)
  631. {
  632. rt_err_t result;
  633. rt_device_t wifi_device;
  634. rw009_cmd_softap softap;
  635. wifi_device = rt_device_find("w0");
  636. if(wifi_device == RT_NULL)
  637. return -RT_ENOSYS;
  638. strncpy( softap.ssid, SSID, sizeof(softap.ssid) );
  639. strncpy( softap.passwd, passwd, sizeof(softap.passwd) );
  640. softap.security = security;
  641. softap.channel = channel;
  642. result = rt_device_control(wifi_device,
  643. RW009_CMD_SOFTAP,
  644. (void *)&softap);
  645. return result;
  646. }
  647. int32_t rw009_rssi(void)
  648. {
  649. rt_err_t result;
  650. struct rw009_wifi * wifi_device;
  651. wifi_device = (struct rw009_wifi *)rt_device_find("w0");
  652. if(wifi_device == RT_NULL)
  653. return 0;
  654. if(wifi_device->active == 0)
  655. return 0;
  656. // SCAN
  657. result = rt_device_control((rt_device_t)wifi_device,
  658. RW009_CMD_RSSI,
  659. RT_NULL);
  660. if(result == RT_EOK)
  661. {
  662. return wifi_device->ap_info.rssi;
  663. }
  664. return 0;
  665. }
  666. #ifdef RT_USING_FINSH
  667. #include <finsh.h>
  668. static rt_err_t rw009_scan(void)
  669. {
  670. rt_err_t result;
  671. struct rw009_wifi * wifi_device;
  672. wifi_device = (struct rw009_wifi *)rt_device_find("w0");
  673. rt_kprintf("\nCMD RW009_CMD_SCAN \n");
  674. result = rt_device_control((rt_device_t)wifi_device,
  675. RW009_CMD_SCAN,
  676. RT_NULL);
  677. rt_kprintf("CMD RW009_CMD_SCAN result:%d\n", result);
  678. if(result == RT_EOK)
  679. {
  680. uint32_t i;
  681. rw009_ap_info *ap_info;
  682. for(i=0; i<wifi_device->ap_scan_count; i++)
  683. {
  684. ap_info = &wifi_device->ap_scan[i];
  685. rt_kprintf("AP #%02d SSID: %-32.32s\n", i, ap_info->ssid );
  686. }
  687. }
  688. return result;
  689. }
  690. FINSH_FUNCTION_EXPORT(rw009_scan, SACN and list AP.);
  691. FINSH_FUNCTION_EXPORT(rw009_join, RW009 join to AP.);
  692. FINSH_FUNCTION_EXPORT(rw009_rssi, get RW009 current AP rssi.);
  693. #endif // RT_USING_FINSH