📄 zd1201.c
字号:
return 0; } err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); if (err) return err; zd->dev->type = ARPHRD_ETHER; switch(*mode) { case IW_MODE_MONITOR: monitor = 1; zd->dev->type = ARPHRD_IEEE80211; /* Make sure we are no longer associated with by setting an 'impossible' essid. (otherwise we mess up firmware) */ zd1201_join(zd, "\0-*#\0", 5); /* Put port in pIBSS */ case 8: /* No pseudo-IBSS in wireless extensions (yet) */ porttype = ZD1201_PORTTYPE_PSEUDOIBSS; break; case IW_MODE_ADHOC: porttype = ZD1201_PORTTYPE_IBSS; break; case IW_MODE_INFRA: porttype = ZD1201_PORTTYPE_BSS; break; default: return -EINVAL; } err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); if (err) return err; if (zd->monitor && !monitor) { zd1201_disable(zd); *(__le16 *)buffer = cpu_to_le16(zd->essidlen); memcpy(buffer+2, zd->essid, zd->essidlen); err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buffer, IW_ESSID_MAX_SIZE+2, 1); if (err) return err; } zd->monitor=monitor; /* If monitor mode is set we don't actually turn it on here since it * is done during mac reset anyway (see zd1201_mac_enable). */ zd1201_mac_reset(zd); return 0;}static int zd1201_get_mode(struct net_device *dev, struct iw_request_info *info, __u32 *mode, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short porttype; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); if (err) return err; switch(porttype) { case ZD1201_PORTTYPE_IBSS: *mode = IW_MODE_ADHOC; break; case ZD1201_PORTTYPE_BSS: *mode = IW_MODE_INFRA; break; case ZD1201_PORTTYPE_WDS: *mode = IW_MODE_REPEAT; break; case ZD1201_PORTTYPE_PSEUDOIBSS: *mode = 8;/* No Pseudo-IBSS... */ break; case ZD1201_PORTTYPE_AP: *mode = IW_MODE_MASTER; break; default: dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", porttype); *mode = IW_MODE_AUTO; } if (zd->monitor) *mode = IW_MODE_MONITOR; return 0;}static int zd1201_get_range(struct net_device *dev, struct iw_request_info *info, struct iw_point *wrq, char *extra){ struct iw_range *range = (struct iw_range *)extra; wrq->length = sizeof(struct iw_range); memset(range, 0, sizeof(struct iw_range)); range->we_version_compiled = WIRELESS_EXT; range->we_version_source = WIRELESS_EXT; range->max_qual.qual = 128; range->max_qual.level = 128; range->max_qual.noise = 128; range->max_qual.updated = 7; range->encoding_size[0] = 5; range->encoding_size[1] = 13; range->num_encoding_sizes = 2; range->max_encoding_tokens = ZD1201_NUMKEYS; range->num_bitrates = 4; range->bitrate[0] = 1000000; range->bitrate[1] = 2000000; range->bitrate[2] = 5500000; range->bitrate[3] = 11000000; range->min_rts = 0; range->min_frag = ZD1201_FRAGMIN; range->max_rts = ZD1201_RTSMAX; range->min_frag = ZD1201_FRAGMAX; return 0;}/* Little bit of magic here: we only get the quality if we poll * for it, and we never get an actual request to trigger such * a poll. Therefore we 'assume' that the user will soon ask for * the stats after asking the bssid. */static int zd1201_get_wap(struct net_device *dev, struct iw_request_info *info, struct sockaddr *ap_addr, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; unsigned char buffer[6]; if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { /* Unfortunately the quality and noise reported is useless. they seem to be accumulators that increase until you read them, unless we poll on a fixed interval we can't use them */ /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ zd->iwstats.qual.updated = 2; } return zd1201_getconfig(zd,ZD1201_RID_CURRENTBSSID,ap_addr->sa_data,6);}static int zd1201_set_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *srq, char *extra){ /* We do everything in get_scan */ return 0;}static int zd1201_get_scan(struct net_device *dev, struct iw_request_info *info, struct iw_point *srq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; int err, i, j, enabled_save; struct iw_event iwe; char *cev = extra; char *end_buf = extra + IW_SCAN_MAX_DATA; /* No scanning in AP mode */ if (zd->ap) return -EOPNOTSUPP; /* Scan doesn't seem to work if disabled */ enabled_save = zd->mac_enabled; zd1201_enable(zd); zd->rxdatas = 0; err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, ZD1201_INQ_SCANRESULTS, 0, 0); if (err) return err; wait_event_interruptible(zd->rxdataq, zd->rxdatas); if (!zd->rxlen) return -EIO; if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) return -EIO; for(i=8; i<zd->rxlen; i+=62) { iwe.cmd = SIOCGIWAP; iwe.u.ap_addr.sa_family = ARPHRD_ETHER; memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_ADDR_LEN); iwe.cmd = SIOCGIWESSID; iwe.u.data.length = zd->rxdata[i+16]; iwe.u.data.flags = 1; cev = iwe_stream_add_point(cev, end_buf, &iwe, zd->rxdata+i+18); iwe.cmd = SIOCGIWMODE; if (zd->rxdata[i+14]&0x01) iwe.u.mode = IW_MODE_MASTER; else iwe.u.mode = IW_MODE_ADHOC; cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_UINT_LEN); iwe.cmd = SIOCGIWFREQ; iwe.u.freq.m = zd->rxdata[i+0]; iwe.u.freq.e = 0; cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_FREQ_LEN); iwe.cmd = SIOCGIWRATE; iwe.u.bitrate.fixed = 0; iwe.u.bitrate.disabled = 0; for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; cev=iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_PARAM_LEN); } iwe.cmd = SIOCGIWENCODE; iwe.u.data.length = 0; if (zd->rxdata[i+14]&0x10) iwe.u.data.flags = IW_ENCODE_ENABLED; else iwe.u.data.flags = IW_ENCODE_DISABLED; cev = iwe_stream_add_point(cev, end_buf, &iwe, NULL); iwe.cmd = IWEVQUAL; iwe.u.qual.qual = zd->rxdata[i+4]; iwe.u.qual.noise= zd->rxdata[i+2]/10-100; iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; iwe.u.qual.updated = 7; cev = iwe_stream_add_event(cev, end_buf, &iwe, IW_EV_QUAL_LEN); } if (!enabled_save) zd1201_disable(zd); srq->length = cev - extra; srq->flags = 0; return 0;}static int zd1201_set_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid){ struct zd1201 *zd = (struct zd1201 *)dev->priv; if (data->length > IW_ESSID_MAX_SIZE) return -EINVAL; if (data->length < 1) data->length = 1; zd->essidlen = data->length-1; memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); memcpy(zd->essid, essid, data->length); return zd1201_join(zd, zd->essid, zd->essidlen);}static int zd1201_get_essid(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *essid){ struct zd1201 *zd = (struct zd1201 *)dev->priv; memcpy(essid, zd->essid, zd->essidlen); data->flags = 1; data->length = zd->essidlen; return 0;}static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, struct iw_point *data, char *nick){ strcpy(nick, "zd1201"); data->flags = 1; data->length = strlen(nick); return 0;}static int zd1201_set_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short rate; int err; switch (rrq->value) { case 1000000: rate = ZD1201_RATEB1; break; case 2000000: rate = ZD1201_RATEB2; break; case 5500000: rate = ZD1201_RATEB5; break; case 11000000: default: rate = ZD1201_RATEB11; break; } if (!rrq->fixed) { /* Also enable all lower bitrates */ rate |= rate-1; } err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); if (err) return err; return zd1201_mac_reset(zd);}static int zd1201_get_rate(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short rate; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); if (err) return err; switch(rate) { case 1: rrq->value = 1000000; break; case 2: rrq->value = 2000000; break; case 5: rrq->value = 5500000; break; case 11: rrq->value = 11000000; break; default: rrq->value = 0; } rrq->fixed = 0; rrq->disabled = 0; return 0;}static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; int err; short val = rts->value; if (rts->disabled || !rts->fixed) val = ZD1201_RTSMAX; if (val > ZD1201_RTSMAX) return -EINVAL; if (val < 0) return -EINVAL; err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); if (err) return err; return zd1201_mac_reset(zd);}static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, struct iw_param *rts, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short rtst; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); if (err) return err; rts->value = rtst; rts->disabled = (rts->value == ZD1201_RTSMAX); rts->fixed = 1; return 0;}static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *frag, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; int err; short val = frag->value; if (frag->disabled || !frag->fixed) val = ZD1201_FRAGMAX; if (val > ZD1201_FRAGMAX) return -EINVAL; if (val < ZD1201_FRAGMIN) return -EINVAL; if (val & 1) return -EINVAL; err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); if (err) return err; return zd1201_mac_reset(zd);}static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, struct iw_param *frag, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short fragt; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); if (err) return err; frag->value = fragt; frag->disabled = (frag->value == ZD1201_FRAGMAX); frag->fixed = 1; return 0;}static int zd1201_set_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ return 0;}static int zd1201_get_retry(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ return 0;}static int zd1201_set_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short i; int err, rid; if (erq->length > ZD1201_MAXKEYLEN) return -EINVAL; i = (erq->flags & IW_ENCODE_INDEX)-1; if (i == -1) { err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); if (err) return err; } else { err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); if (err) return err; } if (i < 0 || i >= ZD1201_NUMKEYS) return -EINVAL; rid = ZD1201_RID_CNFDEFAULTKEY0 + i; err = zd1201_setconfig(zd, rid, key, erq->length, 1); if (err) return err; zd->encode_keylen[i] = erq->length; memcpy(zd->encode_keys[i], key, erq->length); i=0; if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { i |= 0x01; zd->encode_enabled = 1; } else zd->encode_enabled = 0; if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { i |= 0x02; zd->encode_restricted = 1; } else zd->encode_restricted = 0; err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); if (err) return err; if (zd->encode_enabled) i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; else i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); if (err) return err; return zd1201_mac_reset(zd);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -