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