📄 sm_drv_ioctl_umac.c
字号:
struct net_local *lp = dev->priv; struct list_head *ptr; struct sm_drv_bss_wpa_ie *bss = NULL; if (down_trylock(&lp->wpa_sem)) return; list_for_each(ptr, &lp->bss_wpa_list) { bss = list_entry(ptr, struct sm_drv_bss_wpa_ie, list); if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { /* AP is here, removing it...*/ DEBUG(DBG_WPA, "Removing " MACSTR " from wpa list...\n", MAC2STR(bssid)); list_del(&bss->list); lp->num_bss_wpa--; kfree(bss); break; } } up(&lp->wpa_sem);}void sm_drv_wpa_ie_clean(struct net_device *dev){ struct net_local *lp = dev->priv; struct list_head *ptr, *n; if (down_trylock(&lp->wpa_sem)) return; list_for_each_safe(ptr, n, &lp->bss_wpa_list) { struct sm_drv_bss_wpa_ie *bss; bss = list_entry(ptr, struct sm_drv_bss_wpa_ie, list); list_del(&bss->list); kfree(bss); } lp->num_bss_wpa = 0; up(&lp->wpa_sem);}void sm_drv_update_stats(void * data){ struct net_device * dev = (struct net_device *)data; struct net_local * lp = dev->priv; struct obj_bss bss; uint8_t bssid[ETH_ALEN]; uint32_t noise_floor, frame_stats; sm_drv_oid_get(dev, DOT11_OID_NOISEFLOOR, (void*)&noise_floor, sizeof(uint32_t)); lp->iwstatistics.qual.noise = noise_floor; /* copy this MAC to the bss */ bss.ext = 1; if (sm_drv_oid_get(dev, DOT11_OID_BSSID, (void*)bssid, ETH_ALEN * sizeof(uint8_t)) < 0) return; memcpy(bss.address, bssid, ETH_ALEN); /* now ask for the corresponding bss */ if (sm_drv_oid_get(dev, DOT11_OID_BSSFIND, (void *)&bss, sizeof(struct obj_bss)) < 0) { bss.ext = 0; if (sm_drv_oid_get(dev, DOT11_OID_BSSFIND, (void *)&bss, sizeof(struct obj_bss)) < 0) return; } /* report the rssi and use it to calculate * link quality through a signal-noise * ratio */ lp->iwstatistics.qual.level = bss.rssi; lp->iwstatistics.qual.qual = bss.rssi - lp->iwstatistics.qual.noise; /* report that the stats are new */ lp->iwstatistics.qual.updated = 0x7; /* Rx : unable to decrypt the MPDU */ sm_drv_oid_get(dev, DOT11_OID_PRIVRXFAILED, (void*)&frame_stats, sizeof(uint32_t)); lp->iwstatistics.discard.code = frame_stats; /* Tx : Max MAC retries num reached */ sm_drv_oid_get(dev, DOT11_OID_MPDUTXFAILED, (void*)&frame_stats, sizeof(uint32_t)); lp->iwstatistics.discard.retries = frame_stats; return;}struct iw_statistics * sm_drv_get_wireless_stats(struct net_device *dev){ struct net_local *lp = dev->priv; if(!lp->sm_initialization) { memset(&lp->iwstatistics, 0, sizeof(struct iw_statistics)); return &lp->iwstatistics; } lp->iwstatistics.qual.updated = 0; /* * Update our wireless stats, but do not schedule to often * (max 1 HZ) */ if ((lp->stats_timestamp == 0) || time_after(jiffies, lp->stats_timestamp + 1 * HZ)) { schedule_work(&lp->stats_work); lp->stats_timestamp = jiffies; } return &lp->iwstatistics;}static int sm_drv_get_name(struct net_device *dev, struct iw_request_info *info, char *cwrq, char *extra){ struct net_local *lp = dev->priv; char *capabilities; uint32_t ret, profile; DEBUG(DBG_IOCTL, "GET NAME\n"); if(!lp->sm_initialization) { capabilities = "NOT READY"; ret = 0; goto out; } ret = sm_drv_oid_get(dev, DOT11_OID_PROFILES, (void *)&profile, sizeof(uint32_t)); if (ret < 0) { capabilities = "ERROR"; goto out; } DEBUG(DBG_IOCTL, "sm_drv_get_name: name-> 0x%x\n", profile); switch (profile) { case DOT11_PROFILE_B_ONLY: capabilities = "IEEE 802.11b"; break; case DOT11_PROFILE_MIXED: capabilities = "IEEE 802.11b/g"; break; case DOT11_PROFILE_MIXED_LONG: capabilities = "IEEE 802.11b/g-long"; break; case DOT11_PROFILE_G_ONLY: capabilities = "IEEE 802.11g"; break; case DOT11_PROFILE_TEST: capabilities = "TEST profile"; break; case DOT11_PROFILE_B_WIFI: capabilities = "IEEE 802.11b wifi"; break; case DOT11_PROFILE_MIXED_SHORT: capabilities = "IEEE 802.1b/g-short"; break; default: capabilities = "Unknown profile"; /* Default */ break; } out: strncpy(cwrq, capabilities, IFNAMSIZ); return ret;}static int sm_drv_set_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra){ int ret = 0; uint32_t freq; DEBUG(DBG_IOCTL, "SET FREQ: fwrq->m : %d fwrq->e : %d\n", fwrq->m, fwrq->e); if (fwrq->m < 1000) /* we have a channel number */ freq = freq_of_channel(fwrq->m); else freq = fwrq->m/1000; DEBUG(DBG_IOCTL, "SET FREQ: freq is %d\n", freq); if (!freq) return -EINVAL; else { ret = sm_drv_oid_set(dev, DOT11_OID_FREQUENCY, (void *)&freq, sizeof(uint32_t)); if (ret < 0) return ret; } return -EINPROGRESS;}static int sm_drv_get_freq(struct net_device *dev, struct iw_request_info *info, struct iw_freq *fwrq, char *extra){ uint32_t data[2]; DEBUG(DBG_IOCTL, "GET FREQ\n"); sm_drv_oid_get(dev, DOT11_OID_FREQUENCY, (void *)data, 2 * sizeof(uint32_t)); fwrq->m = channel_of_freq(data[0] / 1000); fwrq->e = 0; return 0;}static int sm_drv_set_mode(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ struct net_local * lp = dev->priv; uint32_t sm_mode, mode, current_mode, err, bss_type, profile, ret, commit = 0; DEBUG(DBG_IOCTL, "SET MODE\n"); mode = *(uint32_t *)uwrq; switch (mode) { case IW_MODE_INFRA: mode = DOT11_MODE_CLIENT; sm_mode = SM_MODE_CLIENT; bss_type = DOT11_BSSTYPE_INFRA; profile = DOT11_PROFILE_MIXED; dev->type = ARPHRD_ETHER; break; case IW_MODE_ADHOC: mode = DOT11_MODE_CLIENT; sm_mode = SM_MODE_CLIENT; bss_type = DOT11_BSSTYPE_IBSS; /* When creating an Ad-Hoc network, we must be B only (wifi requirement) */ profile = DOT11_PROFILE_B_ONLY; dev->type = ARPHRD_ETHER; break; case IW_MODE_MASTER: return -1;#if 0 /* AP mode unsupported for now */ mode = DOT11_MODE_AP; sm_mode = SM_MODE_AP; bss_type = DOT11_BSSTYPE_INFRA; profile = DOT11_PROFILE_MIXED; break;#endif case IW_MODE_MONITOR: mode = MODE_PROMISCUOUS; sm_mode = SM_MODE_PROMISCUOUS; bss_type = DOT11_BSSTYPE_NONE; dev->type = ARPHRD_IEEE80211; break; default: return -EINVAL; } ret = sm_drv_oid_get(dev, GEN_OID_MODE, (void *)¤t_mode, sizeof(uint32_t)); if (ret < 0) return ret; DEBUG(DBG_IOCTL, "sm_drv_ioctl: Setting Mode to %d (current: %d)\n", mode, current_mode); if (mode != current_mode) { spin_lock_bh(&lp->sm_lock); lp->sm_mode = sm_mode; spin_unlock_bh(&lp->sm_lock); err = sm_drv_reset(dev, sm_mode); if(err < 0) return -EINVAL; } ret = sm_drv_oid_set(dev, DOT11_OID_PROFILES, (void*)&profile, sizeof(uint32_t)); if (ret < 0) return ret; if (bss_type == DOT11_BSSTYPE_IBSS) { uint32_t preamble_settings = DOT11_PREAMBLESETTING_LONG; ret = sm_drv_oid_set(dev, DOT11_OID_PREAMBLESETTINGS, (void*)&preamble_settings, sizeof(uint32_t)); if (ret < 0) return ret; } ret = sm_drv_oid_set(dev, DOT11_OID_BSSTYPE, (void*)&bss_type, sizeof(uint32_t)); if (ret < 0) return ret; lp->bss_type = bss_type; ret = sm_drv_oid_set(dev, GEN_OID_COMMIT, (void*)&commit, sizeof(uint32_t)); if (ret < 0) return ret; return 0;}static int sm_drv_get_mode(struct net_device *dev, struct iw_request_info *info, __u32 * uwrq, char *extra){ uint32_t mode, ret, bss_type; DEBUG(DBG_IOCTL, "GET MODE\n"); ret = sm_drv_oid_get(dev, GEN_OID_MODE, (void *)&mode, sizeof(uint32_t)); if (ret < 0) return ret; ret = sm_drv_oid_get(dev, DOT11_OID_BSSTYPE, (void *)&bss_type, sizeof(uint32_t)); if (ret < 0) return ret; DEBUG(DBG_IOCTL, "sm_drv_get_mode: mode-> 0x%x\n", mode); switch (mode & 0xff) { case DOT11_MODE_CLIENT: if (bss_type == DOT11_BSSTYPE_INFRA) mode = IW_MODE_INFRA; /* Client Mode */ else if (bss_type == DOT11_BSSTYPE_IBSS) mode = IW_MODE_ADHOC; /* Ad-Hoc mode */ break; case DOT11_MODE_AP: mode = IW_MODE_MASTER; /* AP Mode */ break; case MODE_PROMISCUOUS: mode = IW_MODE_MONITOR; /* Listen only */ break; default: mode = IW_MODE_AUTO; /* Default */ break; } *uwrq = mode; return 0;}/* * We use DOT11_OID_EDTHRESHOLD. From what I guess the card will not try to * emit data if (sensitivity > rssi - noise) (in dBm). */static int sm_drv_set_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ uint32_t sens; DEBUG(DBG_IOCTL, "SET SENS\n"); /* by default the card sets this to 20. */ sens = vwrq->disabled ? 20 : vwrq->value; /* set the ed threshold. */ return sm_drv_oid_set(dev, DOT11_OID_EDTHRESHOLD, (void*)&sens, sizeof(uint32_t)); }static int sm_drv_get_sens(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ int ret; uint32_t sens; DEBUG(DBG_IOCTL, "GET SENS\n"); ret = sm_drv_oid_get(dev, DOT11_OID_EDTHRESHOLD, (void*)&sens, sizeof(uint32_t)); if (ret < 0) return ret; vwrq->value = sens; vwrq->disabled = (vwrq->value == 0); vwrq->fixed = 1; return 0;}static int sm_drv_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *dwrq, char *extra){ struct iw_range *range = (struct iw_range *) extra; uint8_t data[17]; int i, ret, freq_obj_size; struct obj_frequencies * freq; void * frequencies; DEBUG(DBG_IOCTL, "GET RANGE\n"); freq_obj_size = (IW_MAX_FREQUENCIES + 1)* 2 * sizeof(uint8_t); frequencies = kmalloc(freq_obj_size, GFP_ATOMIC); memset(range, 0, sizeof (struct iw_range)); dwrq->length = sizeof (struct iw_range); /* set the wireless extension version number */ range->we_version_source = SUPPORTED_WIRELESS_EXT; range->we_version_compiled = WIRELESS_EXT; /* Now the encoding capabilities */ range->num_encoding_sizes = 3; /* 64(40) bits WEP */ range->encoding_size[0] = 5; /* 128(104) bits WEP */ range->encoding_size[1] = 13; /* 256 bits for WPA-PSK */ range->encoding_size[2] = 32; /* 4 keys are allowed */ range->max_encoding_tokens = 4; /* we don't know the quality range... */ range->max_qual.level = 0; range->max_qual.noise = 0; range->max_qual.qual = 0; /* these value describe an average quality. Needs more tweaking... */ range->avg_qual.level = -80; /* -80 dBm */ range->avg_qual.noise = 0; /* don't know what to put here */ range->avg_qual.qual = 0; range->sensitivity = 200; /* retry limit capabilities */ range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; range->retry_flags = IW_RETRY_LIMIT; range->r_time_flags = IW_RETRY_LIFETIME; /* I don't know the range. Put stupid things here */ range->min_retry = 1; range->max_retry = 65535; range->min_r_time = 1024; range->max_r_time = 65535 * 1024; /* txpower is supported in dBm's */ range->txpower_capa = IW_TXPOW_DBM; /* * Request the device for the supported frequencies * not really revelant since some devices will report the 5 GHz band * frequencies even if they don't support them. */ ret = sm_drv_oid_get(dev, DOT11_OID_SUPPORTEDFREQUENCIES, frequencies, freq_obj_size); if (ret < 0) return ret; freq = (struct obj_frequencies *)frequencies; range->num_channels = freq->nr; range->num_frequency = freq->nr; for (i = 0; i < (int)freq->nr; i++) { range->freq[i].m = freq->mhz[i]; range->freq[i].e = 6; range->freq[i].i = i + 1; }#if 0 /* * Frequencies are not listed in the right order. The reordering is probably * firmware dependant and thus should work for everyone. */ m = min(IW_MAX_FREQUENCIES, (int) freq->nr); for (i = 0; i < m - 12; i++) { range->freq[i].m = freq->mhz[12 + i]; range->freq[i].e = 6; range->freq[i].i = i + 1; } for (i = m - 12; i < m; i++) { range->freq[i].m = freq->mhz[i - m + 12]; range->freq[i].e = 6; range->freq[i].i = i + 23; }#endif ret = sm_drv_oid_get(dev, DOT11_OID_SUPPORTEDRATES, (void *)data, 17 * sizeof(uint8_t)); if (ret < 0) return ret; /* We got an array of char. It is NULL terminated. */ i = 0; while ((i < IW_MAX_BITRATES) && (data[i] != 0)) { /* the result must be in bps. The card gives us 500Kbps */ range->bitrate[i] = (__s32) (data[i] >> 1); range->bitrate[i] *= 1000000; i++; } range->num_bitrates = i; return 0;}static int sm_drv_set_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ uint8_t bssid[ETH_ALEN]; int ret; DEBUG(DBG_IOCTL, "SET WAP\n"); if (awrq->sa_family != ARPHRD_ETHER) return -EINVAL; /* prepare the structure for the set object */ memcpy(bssid, awrq->sa_data, ETH_ALEN); /* set the bssid -- does this make sense when in AP mode? */ ret = sm_drv_oid_set(dev, DOT11_OID_BSSID, (void*)bssid, ETH_ALEN * sizeof(uint8_t)); if (ret < 0) return ret; return -EINPROGRESS; /* Call commit handler */}static int sm_drv_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *awrq, char *extra){ uint8_t bssid[ETH_ALEN] = {0x0,0x0,0x0,0x0,0x0,0x0}; DEBUG(DBG_IOCTL, "GET WAP\n"); sm_drv_oid_get(dev, DOT11_OID_BSSID, (void*)bssid, ETH_ALEN * sizeof(uint8_t)); memcpy(awrq->sa_data, bssid, ETH_ALEN); awrq->sa_family = ARPHRD_ETHER; return 0;}static int sm_drv_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *vwrq, char *extra){ int ret = 0; struct obj_ssid essid; int16_t scan = -1; uint32_t scan_mode, flush_bss_list = 1; struct net_local *lp = dev->priv; uint32_t bgr_scan_disable = 1; if (vwrq == NULL) return -EINVAL; /* First we flush the UMAC's AP list*/ ret = sm_drv_oid_set(dev, DOT11_OID_BSSLISTFLUSH, (void*)&flush_bss_list, sizeof(uint32_t)); if (ret < 0) return ret; if (vwrq->flags & IW_SCAN_THIS_ESSID) { if (vwrq->length > 0) { essid.length = vwrq->length - 1; memcpy(essid.octets, vwrq->pointer, essid.length + 1); } else { essid.length = 0; memset(essid.octets, 0, sizeof(essid.octets)); } scan_mode = SCAN_MODE_ACTIVE; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -