830d9e62754d7a72d8fcbedb1818f6e480443990
[mardrone] / mardrone / ARDrone_SDK_Version_1_8_20110726 / ARDroneLib / VP_SDK / VP_Com / elinux / vp_com_wifi.c
1 #include <VP_Com/vp_com_error.h>
2 #include <VP_Com/vp_com_socket.h>
3
4 #include "vp_com_wifi.h"
5 #include "vp_com_config_itf.h"
6
7 #include <VP_Os/vp_os_malloc.h>
8 #include <VP_Os/vp_os_print.h>
9 #include <VP_Os/vp_os_delay.h>
10
11 #define PROC_NET_DEV "/proc/net/dev"
12
13 #include <netdb.h>
14 #include <sys/socket.h>
15 #include "vp_com_interface.h"
16 #include <unistd.h>
17
18 #ifdef USE_BROADCOM
19 #include "vp_com_wlc.h"
20 #endif
21
22 #ifdef USE_IWLIB
23 #include <iwlib.h>
24 #endif
25
26 #include <net/if.h>
27 #include <netinet/in.h>
28
29
30 C_RESULT vp_com_wf_init(void)
31 {
32   return VP_COM_OK;
33 }
34
35 C_RESULT vp_com_wf_shutdown(void)
36 {
37   return VP_COM_OK;
38 }
39
40 C_RESULT vp_com_wf_network_adapter_lookup(vp_com_network_adapter_lookup_t callback)
41 {
42   char buff[1024];
43
44   FILE* fh = fopen( PROC_NET_DEV, "r" );
45
46   if(fh != NULL)
47   {
48     // eat first two lines
49     if( fgets( buff, sizeof(buff), fh ) && fgets( buff, sizeof(buff), fh ) )
50     {
51       while( fgets( buff, sizeof(buff), fh ) )
52       {
53         // Do parsing here and invoke callback if an interface matches our needs
54       }
55     }
56
57     fclose( fh );
58   }
59
60   return VP_COM_OK;
61 }
62
63 C_RESULT vp_com_wf_inquire(const char* deviceName, vp_com_inquiry_t callback, uint32_t timeout)
64 {
65   return VP_COM_OK;
66 }
67
68 #ifdef USE_BROADCOM
69 C_RESULT vp_com_wf_local_config(vp_com_wifi_config_t* cfg)
70 {
71   C_RESULT res = VP_COM_ERROR;
72
73 #ifdef STA
74 //  wl_scan_results_t* scan_results;
75 //  wl_bss_info_t* bss; uint8_t* ptr;
76 //  int32_t i;
77 //  uint32_t channels_load[10], channel_load, next_channel_load;
78 #endif
79
80   DEBUG_PRINT_SDK("vp_com_wf_local_config\n");
81
82   vp_com_config_itf( cfg->itfName, cfg->localHost, cfg->broadcast, cfg->netmask );
83
84     VP_WLC_BEGIN( cfg->itfName )
85
86       if( vp_wlc_get_magic() == WLC_IOCTL_MAGIC )
87       {
88         vp_wlc_down();
89         vp_wlc_set_country( cfg->country );
90         vp_wlc_up();
91
92         if( vp_wlc_get_radio() != VP_WLC_RADIO_ENABLE )
93           vp_wlc_set_radio(VP_WLC_RADIO_ENABLE);
94
95 #ifdef STA
96        /* for( i = 1; i < 10; i++ )
97           channels_load[i] = 0;
98
99         if( vp_wlc_scan() == 0 )
100         {
101           vp_com_wait_scan_complete();
102           scan_results = vp_wlc_get_scan_results();
103
104           PRINT("Wifi scan gave %d results\n", scan_results->count);
105
106           ptr = (void*)&scan_results->bss_info[0];
107           for(i=0; i < scan_results->count; i++)
108           {
109             int32_t index_min, index, index_max;
110
111             bss = (wl_bss_info_t*) ptr;
112             ptr = (uint8_t*)bss + bss->length;
113
114             index     = bss->chanspec & WL_CHANSPEC_CHAN_MASK;
115             if( index < 10 )
116             {
117               index_min = index-1;
118               index_max = index+1;
119
120               channels_load[index] += 5;
121               if( index_min > 0 )
122                 channels_load[index_min] += 3;
123               if( index_max < 10 )
124                 channels_load[index_max] += 3;
125             }
126
127             PRINT("\t-bss %s on channel %d\n", bss->SSID, bss->chanspec & WL_CHANSPEC_CHAN_MASK );
128           }
129
130           channels_load[0] = 1;
131           channel_load = channels_load[1] + channels_load[2];
132
133           for( i = 2; i < 9; i++ )
134           {
135             next_channel_load = channels_load[i-1] + channels_load[i] + channels_load[i+1];
136
137             if( channel_load > next_channel_load )
138             {
139               channel_load = next_channel_load;
140               channels_load[0] = i;
141             }
142           }
143
144           next_channel_load = channels_load[8] + channels_load[9];
145           if( channel_load > next_channel_load )
146           {
147             channel_load = next_channel_load;
148             channels_load[0] = 9;
149           }
150
151           vp_wlc_set_channel( channels_load[0] );
152
153           PRINT("Setting channel %d\n", channels_load[0]);
154
155         }*/
156 #endif
157
158         vp_wlc_set_infrastructure( (cfg->infrastructure == 1) ? VP_WLC_INFRASTRUCTURE : VP_WLC_ADHOC );
159         vp_wlc_set_authentication( (cfg->secure == 1) ? VP_WLC_AUTH_SHARED : VP_WLC_AUTH_OPEN );
160
161         res = VP_COM_OK;
162       }
163 #ifdef STA
164       vp_wlc_down();
165 #endif
166     VP_WLC_END
167
168   return res;
169 }
170 #endif
171
172 #ifdef USE_IWLIB
173 C_RESULT vp_com_wf_local_config(vp_com_wifi_config_t* cfg)
174 {
175         C_RESULT res=C_FAIL;
176         int wlsock = -1;
177         int16_t key_flags = 0;
178         wireless_config iwconf;
179
180         // If network is secure, configure it now.
181         if(cfg && cfg->secure==1)
182         {
183                 vp_com_config_itf( cfg->itfName, cfg->localHost, cfg->broadcast, cfg->netmask );
184
185                 wlsock = iw_sockets_open();
186
187                 res = ( wlsock < 0 ) ? VP_COM_ERROR : VP_COM_OK;
188                 VP_COM_CHECK( res );
189
190                 iw_get_basic_config( wlsock, cfg->itfName, &iwconf );
191                 iwconf.has_nwid = 0;
192                 iwconf.has_freq = 0;
193                 iwconf.has_mode = 0;
194                 iwconf.has_key  = 0;
195
196                 // After watching Linux/kernel/linux/drivers/parrot/net/wireless/ar6000/ar6000/wireless.ext:1041
197                 // it appears we need to clear ssid before setting passkey
198                 //     if (ar->arSsidLen) {
199                 //         return -EIO;
200                 //     }
201                 // So we do set passkey in two passes, first clear ssid then set new passkey
202
203                 iwconf.has_essid = 1;
204                 iwconf.essid_on = 0;
205                 vp_os_memset( &iwconf.essid[0], 0, IW_ESSID_MAX_SIZE+1 );
206
207                 res = iw_set_basic_config( wlsock, cfg->itfName, &iwconf ) < 0 ? C_FAIL : C_OK;
208
209                 // Setup security
210                 iwconf.has_essid = 0;
211                 iwconf.has_key = 1;
212
213                 if(cfg->secure)
214                 {
215                         iwconf.key_size =  iw_in_key_full( wlsock, cfg->itfName, cfg->passkey, (char*)&iwconf.key, &key_flags );
216                         iwconf.key_flags  = IW_ENCODE_ENABLED | IW_ENCODE_RESTRICTED;
217                 }
218                 else
219                 {
220                         vp_os_memset(&iwconf.key[0], 0, IW_ENCODING_TOKEN_MAX);
221                         iwconf.key_flags  = IW_ENCODE_DISABLED;
222                 }
223
224                 res = iw_set_basic_config( wlsock, cfg->itfName, &iwconf ) < 0 ? C_FAIL : C_OK;
225
226                 iw_sockets_close(wlsock);
227         }
228         else
229         {
230                 res=C_OK;
231         }
232         return res;
233 }
234 #else
235 #ifndef USE_BROADCOM
236 C_RESULT vp_com_wf_local_config(vp_com_wifi_config_t* cfg)
237 {
238         return C_OK;
239 }
240 #endif
241 #endif
242
243 #ifdef USE_BROADCOM
244 C_RESULT vp_com_wf_connect(vp_com_t* vp_com, vp_com_wifi_connection_t* connection, int32_t numAttempts)
245 {
246   C_RESULT res = VP_COM_ERROR;
247   ///struct bootp* bootp_data = NULL;
248   vp_com_wifi_config_t* config = (vp_com_wifi_config_t*) vp_com->config;
249
250 #ifdef STA
251   int32_t   attempt;
252   int32_t   ret;
253   bdaddr_t  bdaddr;
254 #endif
255
256   DEBUG_PRINT_SDK("vp_com_wf_connect\n");
257
258   VP_WLC_BEGIN(config->itfName)
259 #ifdef STA
260     vp_wlc_up();
261
262     attempt = 0;
263
264     do
265     {
266 #endif
267       vp_wlc_set_ssid(connection->networkName);
268 #ifdef STA
269       vp_com_wait_set_ssid();
270       attempt ++;
271     }
272     while( ((ret = vp_wlc_get_bssid(&bdaddr)) < 0) && attempt < 10 );
273
274     if(ret >= 0)
275     {
276 #endif
277
278       res = VP_COM_OK;
279
280 #ifdef STA
281       // Disable roaming
282       vp_wlc_disable_roaming();
283     }
284 #endif
285   VP_WLC_END
286
287   if( SUCCEED( res ) )
288   {
289 #ifdef STA
290     PRINT("STA - Joined essid %s\n", connection->networkName);
291 #else // AP
292     PRINT("AP - Created essid %s\n", connection->networkName);
293 #endif // STA
294   }
295   else
296   {
297     DEBUG_PRINT_SDK("vp_com_wf_connect failed\n");
298   }
299   return res;
300 }
301 #endif
302
303 #ifdef USE_IWLIB
304 C_RESULT vp_com_wf_connect(vp_com_t* vp_com, vp_com_wifi_connection_t* connection, int32_t numAttempts)
305 {
306   C_RESULT res;
307   int32_t wlsock;
308   vp_com_wifi_config_t* config = (vp_com_wifi_config_t*)vp_com->config;
309   wireless_config iwconf;
310
311   wlsock = iw_sockets_open();
312
313   res = ( wlsock < 0 ) ? VP_COM_ERROR : VP_COM_OK;
314   VP_COM_CHECK( res );
315
316   iw_get_basic_config( wlsock, config->itfName, &iwconf );
317
318   iwconf.has_nwid = 0;
319   iwconf.has_freq = 0;
320   iwconf.has_key  = 0;
321
322   iwconf.has_mode = 1;
323   iwconf.mode = config->infrastructure ? IW_MODE_INFRA : IW_MODE_ADHOC;
324
325   iwconf.has_essid = 1;
326   iwconf.essid_on = 1;
327
328         // No need to set the network name if it has not change.
329         if(strcmp(&iwconf.essid[0], connection->networkName)!=0)
330         {
331                 strncpy( &iwconf.essid[0], connection->networkName, IW_ESSID_MAX_SIZE+1 );
332
333                 res = iw_set_basic_config( wlsock, config->itfName, &iwconf ) < 0 ? C_FAIL : C_OK;
334         }
335         else
336         {
337                 res=C_OK;
338         }
339
340   if( SUCCEED(res) )
341     PRINT(" OK!\n");
342   else
343     PRINT(" FAILED!\n");
344
345   iw_sockets_close(wlsock);
346
347   return res;
348 }
349 #else
350 #ifndef USE_BROADCOM
351 C_RESULT vp_com_wf_connect(vp_com_t* vp_com, vp_com_wifi_connection_t* connection, int32_t numAttempts)
352 {
353         return C_OK;
354 }
355 #endif
356 #endif
357
358 #ifdef USE_BROADCOM
359 C_RESULT vp_com_wf_disconnect(vp_com_wifi_config_t* config, vp_com_wifi_connection_t* connection)
360 {
361   VP_WLC_BEGIN( config->itfName )
362 #ifdef STA
363     vp_wlc_up();
364     vp_wlc_set_ssid( NULL );
365 //    vp_com_wait_set_ssid();
366 #endif
367     vp_wlc_down();
368   VP_WLC_END
369
370   return VP_COM_OK;
371 }
372 #endif
373
374 #ifdef USE_IWLIB
375 C_RESULT vp_com_wf_disconnect(vp_com_wifi_config_t* cfg, vp_com_wifi_connection_t* connection)
376 {
377   C_RESULT res;
378   int wlsock = -1;
379   int16_t key_flags = 0;
380   wireless_config iwconf;
381
382   wlsock = iw_sockets_open();
383
384   VP_COM_CHECK( ( wlsock < 0 ) ? VP_COM_ERROR : VP_COM_OK );
385
386   vp_os_memset( &iwconf, 0, sizeof(iwconf) );
387
388   iwconf.has_essid = 1;
389
390   res = iw_set_basic_config( wlsock, cfg->itfName, &iwconf ) < 0 ? C_FAIL : C_OK;
391
392   iw_sockets_close(wlsock);
393
394   return res;
395 }
396 #else
397 #ifndef USE_BROADCOM
398 C_RESULT vp_com_wf_disconnect(vp_com_wifi_config_t* cfg, vp_com_wifi_connection_t* connection)
399 {
400         return C_OK;
401 }
402 #endif
403 #endif
404
405 C_RESULT vp_com_wf_get_rssi(vp_com_wifi_config_t* cfg, int32_t* rssi)
406 {
407   /*struct iwreq wrq;
408   iwstats stats;
409   iwrange range;
410
411   int wlsock = iw_sockets_open();
412
413   vp_os_memset(&wrq, 0, sizeof(struct iwreq));
414   iw_get_stats(wlsock, cfg->itfName, &stats, &range, 1);
415   iw_sockets_close(wlsock);*/
416
417 //   struct  iw_statistics
418 //   {
419 //     __u16           status;           // Status * - device dependent for now
420 //     struct iw_quality       qual;     // Quality of the link * (instant/mean/max)
421 //     struct iw_discarded     discard;  // Packet discarded counts
422 //     struct iw_missed        miss;     // Packet missed counts
423 //   };
424 //
425 //   struct iw_range
426 //   {
427 //     ...
428 //     //  Quality of link & SNR stuff */
429 //     //  Quality range (link, level, noise)
430 //     //  If the quality is absolute, it will be in the range [0 ; max_qual],
431 //     //  if the quality is dBm, it will be in the range [max_qual ; 0].
432 //     //  Don't forget that we use 8 bit arithmetics...
433 //     struct iw_quality       max_qual;       // Quality of the link
434 //     //  This should contain the average/typical values of the quality
435 //     //  indicator. This should be the threshold between a "good" and
436 //     //  a "bad" link (example : monitor going from green to orange).
437 //     //  Currently, user space apps like quality monitors don't have any
438 //     //  way to calibrate the measurement. With this, they can split
439 //     //  the range between 0 and max_qual in different quality level
440 //     //  (using a geometric subdivision centered on the average).
441 //     //  I expect that people doing the user space apps will feedback
442 //     //  us on which value we need to put in each driver...
443 //     struct iw_quality       avg_qual;       // Quality of the link
444 //     ...
445 //   };
446 //   struct  iw_quality
447 //   {
448 //     __u8            qual;           // link quality (%retries, SNR, %missed beacons or better...)
449 //     __u8            level;          // signal level (dBm)
450 //     __u8            noise;          // noise level (dBm)
451 //     __u8            updated;        // Flags to know if updated
452 //   };
453
454   //*rssi = stats.qual.qual;
455
456   return VP_COM_OK;
457 }
458
459 C_RESULT vp_com_wf_wait_connections(vp_com_wifi_connection_t** c, vp_com_socket_t* server, vp_com_socket_t* client, int32_t queueLength)
460 {
461   return vp_com_wait_socket(server, client, queueLength);
462 }
463
464 C_RESULT vp_com_wf_open(vp_com_wifi_config_t* config, vp_com_wifi_connection_t* connection, vp_com_socket_t* sck, Read* read, Write* write)
465 {
466   return vp_com_open_socket(sck, read, write);
467 }
468
469 C_RESULT vp_com_wf_close(vp_com_socket_t* socket)
470 {
471   return vp_com_close_socket(socket);
472 }