8 #include <sys/socket.h>
10 #include "vp_com_wlc.h"
12 #include <VP_Com/vp_com.h>
13 #include <VP_Os/vp_os_malloc.h>
14 #include <VP_Os/vp_os_print.h>
16 static int32_t wlsock = 0;
17 static wl_ioctl_t wldata;
18 static struct ifreq ifr;
19 static char buffer[WLC_IOCTL_MAXLEN];
21 //////////////////////////////////////////////////////////////////////////////////////////////////////
23 static int vp_wlc_ioctl(int cmd, void *buffer, int length, bool set)
33 int result = ioctl(wlsock, SIOCDEVPRIVATE, &ifr);
36 perror("ioctl(wlsock, SIOCDEVPRIVATE, &ifr)");
41 static inline int vp_wlc_get(int cmd, void *data, int len)
43 return vp_wlc_ioctl(cmd, data, len, FALSE);
46 static inline int vp_wlc_set(int cmd, void *data, int len)
48 return vp_wlc_ioctl(cmd, data, len, TRUE);
51 static inline int vp_wlc_set_var(void* data, int len)
53 return vp_wlc_set(WLC_SET_VAR, data, len);
56 //////////////////////////////////////////////////////////////////////////////////////////////////////
58 int32_t vp_wlc_begin(const char* itfname)
60 strcpy(ifr.ifr_name, itfname);
61 ifr.ifr_data = (caddr_t) &wldata;
64 wlsock = socket(AF_INET, SOCK_DGRAM, 0);
69 int32_t vp_wlc_end(void)
80 //////////////////////////////////////////////////////////////////////////////////////////////////////
82 int32_t vp_wlc_down(void)
84 return vp_wlc_set(WLC_DOWN, NULL, 0);
87 int32_t vp_wlc_up(void)
89 return vp_wlc_set(WLC_UP, NULL, 0);
92 int32_t vp_wlc_get_magic(void)
94 if(vp_wlc_get(WLC_GET_MAGIC, buffer, sizeof(int32_t)) < 0)
97 return *(int32_t*)buffer;
100 int32_t vp_wlc_set_channel(int32_t channel)
102 return vp_wlc_set(WLC_SET_CHANNEL, &channel, sizeof(int32_t));
105 channel_info_t* vp_wlc_get_channel(int32_t* channel)
107 channel_info_t* channel_info = (channel_info_t*) buffer;
111 if(vp_wlc_get(WLC_GET_CHANNEL, buffer, sizeof(channel_info_t)) < 0)
114 *channel = channel_info->target_channel;
119 int32_t vp_wlc_set_country(const char* country)
121 char *tmp = (char*)country;
122 return vp_wlc_set(WLC_SET_COUNTRY, (void*)tmp, strlen(country) + 1);
125 const char* vp_wlc_get_country(void)
127 if(vp_wlc_get(WLC_GET_COUNTRY, buffer, 4) < 0)
130 return (const char*) buffer;
133 int32_t vp_wlc_set_radio(VP_WLC_RADIO_STATE state)
135 return vp_wlc_set(WLC_SET_RADIO, &state, sizeof(int32_t));
138 int32_t vp_wlc_get_radio(void)
142 if(vp_wlc_get(WLC_GET_RADIO, buffer, sizeof(int32_t)) < 0)
145 radio_state = *(int32_t*) buffer;
147 return VP_WLC_RADIO_ENABLE;
149 return VP_WLC_RADIO_DISABLE;
152 int32_t vp_wlc_set_infrastructure(VP_WLC_INFRA_MODE value)
154 return vp_wlc_set(WLC_SET_INFRA, &value, sizeof(int32_t));
157 int32_t vp_wlc_get_infrastructure(void)
159 if(vp_wlc_get(WLC_GET_INFRA, buffer, sizeof(int32_t)) < 0)
162 return *(int32_t*) buffer;
165 int32_t vp_wlc_set_authentication(VP_WLC_AUTH_MODE mode)
167 return vp_wlc_set(WLC_SET_AUTH, &mode, sizeof(int32_t));
170 int32_t vp_wlc_get_authentication(void)
172 if(vp_wlc_get(WLC_GET_AUTH, buffer, sizeof(int32_t)) < 0)
175 return *(int32_t*) buffer;
178 int32_t vp_wlc_set_ssid(const char* name)
182 vp_os_memset(&ssid, 0, sizeof(wlc_ssid_t));
186 ssid.SSID_len = strlen(name);
187 strncpy((char *)ssid.SSID, name, ssid.SSID_len);
190 return vp_wlc_set(WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t));
193 wlc_ssid_t* vp_wlc_get_ssid(void)
195 if(vp_wlc_get(WLC_GET_SSID, buffer, sizeof(wlc_ssid_t)) < 0)
198 return (wlc_ssid_t*) buffer;
202 int32_t vp_wlc_get_bssid(bdaddr_t* bssid)
204 if(vp_wlc_get(WLC_GET_BSSID, buffer, sizeof(bdaddr_t)) < 0)
207 vp_com_copy_address((bdaddr_t*) buffer, bssid);
213 int32_t vp_wlc_set_security_mode(int32_t wsec)
215 return vp_wlc_set(WLC_SET_WSEC, &wsec, sizeof(int32_t));
218 int32_t vp_wlc_get_security_mode(void)
220 if(vp_wlc_get(WLC_GET_WSEC, buffer, sizeof(int32_t)) < 0)
223 return *(int32_t*)buffer;
226 int32_t vp_wlc_set_wep128_key(const char* wep_key)
230 vp_os_memset(&key, 0, sizeof(wl_wsec_key_t));
231 vp_os_memcpy(&key.data, wep_key, WEP128_KEY_SIZE);
233 key.len = WEP128_KEY_SIZE;
234 key.algo = CRYPTO_ALGO_WEP128;
235 key.flags |= WL_PRIMARY_KEY;
237 return vp_wlc_set(WLC_SET_KEY, &key, sizeof(key));
240 int32_t vp_wlc_set_mac_mode(int32_t mode)
242 return vp_wlc_set(WLC_SET_MACMODE, &mode, sizeof(int32_t));
245 int32_t vp_wlc_get_mac_mode(void)
247 if( vp_wlc_get(WLC_GET_MACMODE, buffer, sizeof(int32_t)) < 0)
250 return *(int32_t*)buffer;
253 static int32_t vp_wlc_set_roam_trigger(int32_t value)
255 return vp_wlc_set(WLC_SET_ROAM_TRIGGER, &value, sizeof(int32_t));
258 static int32_t vp_wlc_get_roam_trigger(int32_t* value)
260 if( vp_wlc_get(WLC_GET_MACMODE, buffer, sizeof(int32_t)) < 0)
263 *value = *(int32_t*)buffer;
268 #define ROAMING_ENABLE_VALUE 0
269 #define ROAMING_DISABLE_VALUE -99
272 int32_t vp_wlc_enable_roaming(void)
274 return vp_wlc_set_roam_trigger(ROAMING_ENABLE_VALUE);
278 int32_t vp_wlc_disable_roaming(void)
280 return vp_wlc_set_roam_trigger(ROAMING_DISABLE_VALUE);
283 // Returns true if roaming is enable. 0 otherwise.
284 bool_t vp_wlc_roaming_enable(void)
289 if( vp_wlc_get_roam_trigger(&value) == 0 )
293 case ROAMING_ENABLE_VALUE:
297 case ROAMING_DISABLE_VALUE:
310 int32_t vp_wlc_scan(void)
313 int32_t ap = 0, oldap = 0;
314 wl_scan_params_t params;
316 vp_os_memset(¶ms, 0, sizeof(params));
317 vp_os_memset(¶ms.bssid, 0xff, sizeof(params.bssid));
319 params.bss_type = DOT11_BSSTYPE_ANY;
320 params.scan_type = -1;
322 params.active_time = -1;
323 params.passive_time = -1;
324 params.home_time = -1;
326 if( vp_wlc_get( WLC_GET_AP, &oldap, sizeof(int32_t) ) < 0 )
330 vp_wlc_set( WLC_SET_AP, &ap, sizeof(int32_t) );
332 if( vp_wlc_get(WLC_SCAN, ¶ms, 64) < 0 )
336 vp_wlc_set( WLC_SET_AP, &oldap, sizeof(oldap) );
341 wl_scan_results_t* vp_wlc_get_scan_results(void)
343 wl_scan_results_t* results = (wl_scan_results_t *) buffer;
345 results->buflen = WLC_IOCTL_MAXLEN - sizeof(wl_scan_results_t);
347 if( vp_wlc_get(WLC_SCAN_RESULTS, buffer, WLC_IOCTL_MAXLEN) < 0 )
353 static bool swap = FALSE;
354 #define dtoh32(i) (swap?bcmswap32(i):i)
355 #define htod32(i) (swap?bcmswap32(i):i)
356 #define DIV_QUO(num, div) ((num)/div) /* Return the quotient of division to avoid floats */
357 #define DIV_REM(num, div) (((num%div) * 100)/div) /* Return the remainder of division */
359 /* Byte swap a 32 bit value */
360 #define BCMSWAP32(val) \
362 (((uint32)(val) & (uint32)0x000000ffUL) << 24) | \
363 (((uint32)(val) & (uint32)0x0000ff00UL) << 8) | \
364 (((uint32)(val) & (uint32)0x00ff0000UL) >> 8) | \
365 (((uint32)(val) & (uint32)0xff000000UL) >> 24)))
368 bcmswap32(uint32 val)
370 return BCMSWAP32(val);
373 #define QDBM_TABLE_LEN 40
374 #define QDBM_OFFSET 153
376 /* Smallest mW value that will round up to the first table entry, QDBM_OFFSET.
377 * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2
379 #define QDBM_TABLE_LOW_BOUND 6493 /* QDBM_TABLE_LOW_BOUND */
381 static const uint16_t nqdBm_to_mW_map[QDBM_TABLE_LEN] = {
382 /* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */
383 /* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000,
384 /* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849,
385 /* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119,
386 /* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811,
387 /* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096
390 static uint16_t wl_qdbm_to_mw(uint8_t qdbm)
393 int idx = qdbm - QDBM_OFFSET;
395 if (idx >= QDBM_TABLE_LEN) {
396 /* clamp to max uint16 mW value */
400 /* scale the qdBm index up to the range of the table 0-40
401 * where an offset of 40 qdBm equals a factor of 10 mW.
408 /* return the mW value scaled down to the correct factor of 10,
409 * adding in factor/2 to get proper rounding.
411 return ((nqdBm_to_mW_map[idx] + factor/2) / factor);
414 static uint8 wl_mw_to_qdbm(uint16 mw)
421 /* handle boundary case */
425 offset = QDBM_OFFSET;
427 /* move mw into the range of the table */
428 while (mw_uint < QDBM_TABLE_LOW_BOUND) {
433 for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) {
434 boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - nqdBm_to_mW_map[qdbm])/2;
435 if (mw_uint < boundary) break;
438 qdbm += (uint8)offset;
443 int32_t vp_wlc_get_instant_power(uint32_t *power)
446 uint8_t buffer[WLC_IOCTL_MAXLEN];
448 bool override = TRUE;
450 strcpy((char*)&buffer[0], "qtxpower");
451 if( vp_wlc_get(WLC_GET_VAR, &buffer[0], strlen((char *)&buffer[0]) + 5) < 0)
454 int_ptr = (uint32 *)&buffer[0];
455 val = dtoh32(*int_ptr);
456 override = (bool)(val & WL_TXPWR_OVERRIDE);
457 val &= ~WL_TXPWR_OVERRIDE;
458 *power = wl_qdbm_to_mw((uint8)((val<0xff?val:0xff)));
463 int32_t vp_wlc_set_instant_power(uint32_t power)
465 unsigned int new_val = 0;
466 uint8_t pwr_buf[WLC_IOCTL_MAXLEN];
468 bool override = TRUE;
470 strcpy((char *)&pwr_buf[0], "qtxpower");
472 new_val = wl_mw_to_qdbm((uint16)(power<=0xffff?power:0xffff));
474 int_ptr = &pwr_buf[strlen((char *)&pwr_buf[0]) + 1];
476 new_val |= WL_TXPWR_OVERRIDE;
477 new_val = htod32(new_val);
478 memcpy(int_ptr, (const void *)&new_val, sizeof(new_val));
480 if( vp_wlc_set(WLC_SET_VAR, &pwr_buf[0], strlen((char *)&pwr_buf[0])+5) < 0 )
483 PRINT("Power set to %d mW\n", power);