00001
00002
00003 #ifdef WIRELESS_EXT
00004
00005 #ifdef in_atomic
00006
00007 #include <linux/smp_lock.h>
00008 #endif
00009
00010
00011 static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev)
00012 {
00013 struct hostap_interface *iface = dev->priv;
00014 local_info_t *local = iface->local;
00015
00016 local->wstats.status = 0;
00017 local->wstats.discard.code =
00018 local->comm_tallies.rx_discards_wep_undecryptable;
00019 local->wstats.discard.misc =
00020 local->comm_tallies.rx_fcs_errors +
00021 local->comm_tallies.rx_discards_no_buffer +
00022 local->comm_tallies.tx_discards_wrong_sa;
00023
00024 #if WIRELESS_EXT > 11
00025 local->wstats.discard.retries =
00026 local->comm_tallies.tx_retry_limit_exceeded;
00027 local->wstats.discard.fragment =
00028 local->comm_tallies.rx_message_in_bad_msg_fragments;
00029 #endif
00030
00031 if (local->iw_mode != IW_MODE_MASTER &&
00032 local->iw_mode != IW_MODE_REPEAT) {
00033 struct hfa384x_comms_quality sq;
00034 #ifdef in_atomic
00035
00036
00037
00038
00039
00040
00041
00042 if (in_atomic()) {
00043 printk(KERN_DEBUG "%s: hostap_get_wireless_stats() "
00044 "called while atomic - skipping signal "
00045 "quality query\n", dev->name);
00046 } else
00047 #endif
00048 if (local->func->get_rid(local->dev,
00049 HFA384X_RID_COMMSQUALITY,
00050 &sq, sizeof(sq), 1) >= 0) {
00051 local->wstats.qual.qual = le16_to_cpu(sq.comm_qual);
00052 local->wstats.qual.level = HFA384X_LEVEL_TO_dBm(
00053 le16_to_cpu(sq.signal_level));
00054 local->wstats.qual.noise = HFA384X_LEVEL_TO_dBm(
00055 le16_to_cpu(sq.noise_level));
00056 local->wstats.qual.updated = 7;
00057 }
00058 }
00059
00060 return &local->wstats;
00061 }
00062
00063
00064 static int prism2_get_datarates(struct net_device *dev, u8 *rates)
00065 {
00066 struct hostap_interface *iface = dev->priv;
00067 local_info_t *local = iface->local;
00068 u8 buf[12];
00069 int len;
00070 u16 val;
00071
00072 len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf,
00073 sizeof(buf), 0);
00074 if (len < 2)
00075 return 0;
00076
00077 val = le16_to_cpu(*(u16 *) buf);
00078
00079 if (len - 2 < val || val > 10)
00080 return 0;
00081
00082 memcpy(rates, buf + 2, val);
00083 return val;
00084 }
00085
00086
00087 static int prism2_get_name(struct net_device *dev,
00088 struct iw_request_info *info,
00089 char *name, char *extra)
00090 {
00091 u8 rates[10];
00092 int len, i, over2 = 0;
00093
00094 len = prism2_get_datarates(dev, rates);
00095
00096 for (i = 0; i < len; i++) {
00097 if (rates[i] == 0x0b || rates[i] == 0x16) {
00098 over2 = 1;
00099 break;
00100 }
00101 }
00102
00103 strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS");
00104
00105 return 0;
00106 }
00107
00108
00109 static void prism2_crypt_delayed_deinit(local_info_t *local,
00110 struct prism2_crypt_data **crypt)
00111 {
00112 struct prism2_crypt_data *tmp;
00113 unsigned long flags;
00114
00115 tmp = *crypt;
00116 *crypt = NULL;
00117
00118 if (tmp == NULL)
00119 return;
00120
00121
00122
00123
00124
00125 spin_lock_irqsave(&local->lock, flags);
00126 list_add(&tmp->list, &local->crypt_deinit_list);
00127 if (!timer_pending(&local->crypt_deinit_timer)) {
00128 local->crypt_deinit_timer.expires = jiffies + HZ;
00129 add_timer(&local->crypt_deinit_timer);
00130 }
00131 spin_unlock_irqrestore(&local->lock, flags);
00132 }
00133
00134
00135 static int prism2_ioctl_siwencode(struct net_device *dev,
00136 struct iw_request_info *info,
00137 struct iw_point *erq, char *keybuf)
00138 {
00139 struct hostap_interface *iface = dev->priv;
00140 local_info_t *local = iface->local;
00141 int i;
00142 int first = 0;
00143
00144 if (erq->flags & IW_ENCODE_DISABLED) {
00145 prism2_crypt_delayed_deinit(local, &local->crypt);
00146 goto done;
00147 }
00148
00149 if (local->crypt != NULL && local->crypt->ops != NULL &&
00150 strcmp(local->crypt->ops->name, "WEP") != 0) {
00151
00152 prism2_crypt_delayed_deinit(local, &local->crypt);
00153 }
00154
00155 if (local->crypt == NULL) {
00156 struct prism2_crypt_data *new_crypt;
00157
00158
00159 new_crypt = (struct prism2_crypt_data *)
00160 kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL);
00161 if (new_crypt == NULL)
00162 return -ENOMEM;
00163 memset(new_crypt, 0, sizeof(struct prism2_crypt_data));
00164 new_crypt->ops = hostap_get_crypto_ops("WEP");
00165 if (!new_crypt->ops) {
00166 request_module("hostap_crypt_wep");
00167 new_crypt->ops = hostap_get_crypto_ops("WEP");
00168 }
00169 if (new_crypt->ops)
00170 new_crypt->priv = new_crypt->ops->init();
00171 if (!new_crypt->ops || !new_crypt->priv) {
00172 kfree(new_crypt);
00173 new_crypt = NULL;
00174
00175 printk(KERN_WARNING "%s: could not initialize WEP: "
00176 "load module hostap_crypt_wep.o\n",
00177 dev->name);
00178 return -EOPNOTSUPP;
00179 }
00180 first = 1;
00181 local->crypt = new_crypt;
00182 }
00183
00184 i = erq->flags & IW_ENCODE_INDEX;
00185 if (i < 1 || i > 4)
00186 i = local->crypt->ops->get_key_idx(local->crypt->priv);
00187 else
00188 i--;
00189 if (i < 0 || i >= WEP_KEYS)
00190 return -EINVAL;
00191
00192 if (erq->length > 0) {
00193 int len = erq->length <= 5 ? 5 : 13;
00194 if (len > erq->length)
00195 memset(keybuf + erq->length, 0, len - erq->length);
00196 local->crypt->ops->set_key(i, keybuf, len, local->crypt->priv);
00197 if (first)
00198 local->crypt->ops->set_key_idx(i, local->crypt->priv);
00199 } else {
00200 if (local->crypt->ops->set_key_idx(i, local->crypt->priv) < 0)
00201 return -EINVAL;
00202 }
00203
00204 done:
00205 local->open_wep = erq->flags & IW_ENCODE_OPEN;
00206
00207 if (hostap_set_encryption(local)) {
00208 printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name);
00209 return -EINVAL;
00210 }
00211
00212
00213
00214
00215
00216
00217 if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) {
00218 printk(KERN_DEBUG "%s: reset_port failed\n", dev->name);
00219 return -EINVAL;
00220 }
00221
00222 return 0;
00223 }
00224
00225
00226 static int prism2_ioctl_giwencode(struct net_device *dev,
00227 struct iw_request_info *info,
00228 struct iw_point *erq, char *key)
00229 {
00230 struct hostap_interface *iface = dev->priv;
00231 local_info_t *local = iface->local;
00232 int i, len;
00233 u16 val;
00234
00235 if (local->crypt == NULL || local->crypt->ops == NULL) {
00236 erq->length = 0;
00237 erq->flags = IW_ENCODE_DISABLED;
00238 return 0;
00239 }
00240
00241 if (strcmp(local->crypt->ops->name, "WEP") != 0) {
00242
00243
00244 erq->length = 0;
00245 erq->flags = IW_ENCODE_ENABLED;
00246 return 0;
00247 }
00248
00249 i = erq->flags & IW_ENCODE_INDEX;
00250 if (i < 1 || i > 4)
00251 i = local->crypt->ops->get_key_idx(local->crypt->priv);
00252 else
00253 i--;
00254 if (i < 0 || i >= WEP_KEYS)
00255 return -EINVAL;
00256
00257 erq->flags = i + 1;
00258
00259
00260
00261 len = local->crypt->ops->get_key(i, key, WEP_KEY_LEN,
00262 local->crypt->priv);
00263 erq->length = (len >= 0 ? len : 0);
00264
00265 if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0)
00266 {
00267 printk("CNFWEPFLAGS reading failed\n");
00268 return -EOPNOTSUPP;
00269 }
00270 le16_to_cpus(&val);
00271 if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED)
00272 erq->flags |= IW_ENCODE_ENABLED;
00273 else
00274 erq->flags |= IW_ENCODE_DISABLED;
00275 if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED)
00276 erq->flags |= IW_ENCODE_RESTRICTED;
00277 else
00278 erq->flags |= IW_ENCODE_OPEN;
00279
00280 return 0;
00281 }
00282
00283
00284 #if WIRELESS_EXT <= 15
00285 static int prism2_ioctl_giwspy(struct net_device *dev,
00286 struct iw_request_info *info,
00287 struct iw_point *srq, char *extra)
00288 {
00289 struct hostap_interface *iface = dev->priv;
00290 local_info_t *local = iface->local;
00291 struct sockaddr addr[IW_MAX_SPY];
00292 struct iw_quality qual[IW_MAX_SPY];
00293
00294 if (local->iw_mode != IW_MODE_MASTER) {
00295 printk("SIOCGIWSPY is currently only supported in Host AP "
00296 "mode\n");
00297 srq->length = 0;
00298 return -EOPNOTSUPP;
00299 }
00300
00301 srq->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_SPY, 0);
00302
00303 memcpy(extra, &addr, sizeof(addr[0]) * srq->length);
00304 memcpy(extra + sizeof(addr[0]) * srq->length, &qual,
00305 sizeof(qual[0]) * srq->length);
00306
00307 return 0;
00308 }
00309 #endif
00310
00311
00312 static int hostap_set_rate(struct net_device *dev)
00313 {
00314 struct hostap_interface *iface = dev->priv;
00315 local_info_t *local = iface->local;
00316 int ret, basic_rates;
00317
00318 basic_rates = local->basic_rates & local->tx_rate_control;
00319 if (!basic_rates || basic_rates != local->basic_rates) {
00320 printk(KERN_INFO "%s: updating basic rate set automatically "
00321 "to match with the new supported rate set\n",
00322 dev->name);
00323 if (!basic_rates)
00324 basic_rates = local->tx_rate_control;
00325
00326 local->basic_rates = basic_rates;
00327 if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
00328 basic_rates))
00329 printk(KERN_WARNING "%s: failed to set "
00330 "cnfBasicRates\n", dev->name);
00331 }
00332
00333 ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL,
00334 local->tx_rate_control) ||
00335 hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES,
00336 local->tx_rate_control) ||
00337 local->func->reset_port(dev));
00338
00339 if (ret) {
00340 printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates "
00341 "setting to 0x%x failed\n",
00342 dev->name, local->tx_rate_control);
00343 }
00344
00345
00346
00347 hostap_update_rates(local);
00348
00349 return ret;
00350 }
00351
00352
00353 static int prism2_ioctl_siwrate(struct net_device *dev,
00354 struct iw_request_info *info,
00355 struct iw_param *rrq, char *extra)
00356 {
00357 struct hostap_interface *iface = dev->priv;
00358 local_info_t *local = iface->local;
00359
00360 if (rrq->fixed) {
00361 switch (rrq->value) {
00362 case 11000000:
00363 local->tx_rate_control = HFA384X_RATES_11MBPS;
00364 break;
00365 case 5500000:
00366 local->tx_rate_control = HFA384X_RATES_5MBPS;
00367 break;
00368 case 2000000:
00369 local->tx_rate_control = HFA384X_RATES_2MBPS;
00370 break;
00371 case 1000000:
00372 local->tx_rate_control = HFA384X_RATES_1MBPS;
00373 break;
00374 default:
00375 local->tx_rate_control = HFA384X_RATES_1MBPS |
00376 HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
00377 HFA384X_RATES_11MBPS;
00378 break;
00379 }
00380 } else {
00381 switch (rrq->value) {
00382 case 11000000:
00383 local->tx_rate_control = HFA384X_RATES_1MBPS |
00384 HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
00385 HFA384X_RATES_11MBPS;
00386 break;
00387 case 5500000:
00388 local->tx_rate_control = HFA384X_RATES_1MBPS |
00389 HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS;
00390 break;
00391 case 2000000:
00392 local->tx_rate_control = HFA384X_RATES_1MBPS |
00393 HFA384X_RATES_2MBPS;
00394 break;
00395 case 1000000:
00396 local->tx_rate_control = HFA384X_RATES_1MBPS;
00397 break;
00398 default:
00399 local->tx_rate_control = HFA384X_RATES_1MBPS |
00400 HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS |
00401 HFA384X_RATES_11MBPS;
00402 break;
00403 }
00404 }
00405
00406 return hostap_set_rate(dev);
00407 }
00408
00409
00410 static int prism2_ioctl_giwrate(struct net_device *dev,
00411 struct iw_request_info *info,
00412 struct iw_param *rrq, char *extra)
00413 {
00414 u16 val;
00415 struct hostap_interface *iface = dev->priv;
00416 local_info_t *local = iface->local;
00417 int ret = 0;
00418
00419 if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) <
00420 0)
00421 return -EINVAL;
00422
00423 if ((val & 0x1) && (val > 1))
00424 rrq->fixed = 0;
00425 else
00426 rrq->fixed = 1;
00427
00428 if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL &&
00429 !local->fw_tx_rate_control) {
00430
00431
00432
00433 rrq->value = local->ap->last_tx_rate > 0 ?
00434 local->ap->last_tx_rate * 100000 : 11000000;
00435 return 0;
00436 }
00437
00438 if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) <
00439 0)
00440 return -EINVAL;
00441
00442 switch (val) {
00443 case HFA384X_RATES_1MBPS:
00444 rrq->value = 1000000;
00445 break;
00446 case HFA384X_RATES_2MBPS:
00447 rrq->value = 2000000;
00448 break;
00449 case HFA384X_RATES_5MBPS:
00450 rrq->value = 5500000;
00451 break;
00452 case HFA384X_RATES_11MBPS:
00453 rrq->value = 11000000;
00454 break;
00455 default:
00456
00457 rrq->value = 11000000;
00458 ret = -EINVAL;
00459 break;
00460 }
00461
00462 return ret;
00463 }
00464
00465
00466 static int prism2_ioctl_siwsens(struct net_device *dev,
00467 struct iw_request_info *info,
00468 struct iw_param *sens, char *extra)
00469 {
00470 struct hostap_interface *iface = dev->priv;
00471 local_info_t *local = iface->local;
00472
00473
00474 if (sens->value < 1 || sens->value > 3)
00475 return -EINVAL;
00476
00477 if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) ||
00478 local->func->reset_port(dev))
00479 return -EINVAL;
00480
00481 return 0;
00482 }
00483
00484 static int prism2_ioctl_giwsens(struct net_device *dev,
00485 struct iw_request_info *info,
00486 struct iw_param *sens, char *extra)
00487 {
00488 struct hostap_interface *iface = dev->priv;
00489 local_info_t *local = iface->local;
00490 u16 val;
00491
00492
00493 if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) <
00494 0)
00495 return -EINVAL;
00496
00497 sens->value = __le16_to_cpu(val);
00498 sens->fixed = 1;
00499
00500 return 0;
00501 }
00502
00503
00504
00505 static int prism2_ioctl_giwaplist(struct net_device *dev,
00506 struct iw_request_info *info,
00507 struct iw_point *data, char *extra)
00508 {
00509 struct hostap_interface *iface = dev->priv;
00510 local_info_t *local = iface->local;
00511 struct sockaddr addr[IW_MAX_AP];
00512 struct iw_quality qual[IW_MAX_AP];
00513
00514 if (local->iw_mode != IW_MODE_MASTER) {
00515 printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported "
00516 "in Host AP mode\n");
00517 data->length = 0;
00518 return -EOPNOTSUPP;
00519 }
00520
00521 data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1);
00522
00523 memcpy(extra, &addr, sizeof(addr[0]) * data->length);
00524 data->flags = 1;
00525 memcpy(extra + sizeof(addr[0]) * data->length, &qual,
00526 sizeof(qual[0]) * data->length);
00527
00528 return 0;
00529 }
00530
00531
00532 static int prism2_ioctl_siwrts(struct net_device *dev,
00533 struct iw_request_info *info,
00534 struct iw_param *rts, char *extra)
00535 {
00536 struct hostap_interface *iface = dev->priv;
00537 local_info_t *local = iface->local;
00538 u16 val;
00539
00540 if (rts->disabled)
00541 val = __constant_cpu_to_le16(2347);
00542 else if (rts->value < 0 || rts->value > 2347)
00543 return -EINVAL;
00544 else
00545 val = __cpu_to_le16(rts->value);
00546
00547 if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) ||
00548 local->func->reset_port(dev))
00549 return -EINVAL;
00550
00551 local->rts_threshold = rts->value;
00552
00553 return 0;
00554 }
00555
00556 static int prism2_ioctl_giwrts(struct net_device *dev,
00557 struct iw_request_info *info,
00558 struct iw_param *rts, char *extra)
00559 {
00560 struct hostap_interface *iface = dev->priv;
00561 local_info_t *local = iface->local;
00562 u16 val;
00563
00564 if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) <
00565 0)
00566 return -EINVAL;
00567
00568 rts->value = __le16_to_cpu(val);
00569 rts->disabled = (rts->value == 2347);
00570 rts->fixed = 1;
00571
00572 return 0;
00573 }
00574
00575
00576 static int prism2_ioctl_siwfrag(struct net_device *dev,
00577 struct iw_request_info *info,
00578 struct iw_param *rts, char *extra)
00579 {
00580 struct hostap_interface *iface = dev->priv;
00581 local_info_t *local = iface->local;
00582 u16 val;
00583
00584 if (rts->disabled)
00585 val = __constant_cpu_to_le16(2346);
00586 else if (rts->value < 256 || rts->value > 2346)
00587 return -EINVAL;
00588 else
00589 val = __cpu_to_le16(rts->value & ~0x1);
00590
00591 local->fragm_threshold = rts->value & ~0x1;
00592 if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val,
00593 2)
00594 || local->func->reset_port(dev))
00595 return -EINVAL;
00596
00597 return 0;
00598 }
00599
00600 static int prism2_ioctl_giwfrag(struct net_device *dev,
00601 struct iw_request_info *info,
00602 struct iw_param *rts, char *extra)
00603 {
00604 struct hostap_interface *iface = dev->priv;
00605 local_info_t *local = iface->local;
00606 u16 val;
00607
00608 if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD,
00609 &val, 2, 1) < 0)
00610 return -EINVAL;
00611
00612 rts->value = __le16_to_cpu(val);
00613 rts->disabled = (rts->value == 2346);
00614 rts->fixed = 1;
00615
00616 return 0;
00617 }
00618
00619
00620 static int hostap_join_ap(struct net_device *dev)
00621 {
00622 struct hostap_interface *iface = dev->priv;
00623 local_info_t *local = iface->local;
00624 struct hfa384x_join_request req;
00625 unsigned long flags;
00626 int i;
00627 struct hfa384x_scan_result *entry;
00628
00629 memcpy(req.bssid, local->preferred_ap, ETH_ALEN);
00630 req.channel = 0;
00631
00632 spin_lock_irqsave(&local->lock, flags);
00633 for (i = 0; i < local->last_scan_results_count; i++) {
00634 if (!local->last_scan_results)
00635 break;
00636 entry = &local->last_scan_results[i];
00637 if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) {
00638 req.channel = entry->chid;
00639 break;
00640 }
00641 }
00642 spin_unlock_irqrestore(&local->lock, flags);
00643
00644 if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req,
00645 sizeof(req))) {
00646 printk(KERN_DEBUG "%s: JoinRequest " MACSTR
00647 " failed\n",
00648 dev->name, MAC2STR(local->preferred_ap));
00649 return -1;
00650 }
00651
00652 printk(KERN_DEBUG "%s: Trying to join BSSID " MACSTR "\n",
00653 dev->name, MAC2STR(local->preferred_ap));
00654
00655 return 0;
00656 }
00657
00658
00659 static int prism2_ioctl_siwap(struct net_device *dev,
00660 struct iw_request_info *info,
00661 struct sockaddr *ap_addr, char *extra)
00662 {
00663 #ifdef PRISM2_NO_STATION_MODES
00664 return -EOPNOTSUPP;
00665 #else
00666 struct hostap_interface *iface = dev->priv;
00667 local_info_t *local = iface->local;
00668
00669 memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN);
00670
00671 if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) {
00672 struct hfa384x_scan_request scan_req;
00673 memset(&scan_req, 0, sizeof(scan_req));
00674 scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
00675 scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
00676 if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST,
00677 &scan_req, sizeof(scan_req))) {
00678 printk(KERN_DEBUG "%s: ScanResults request failed - "
00679 "preferred AP delayed to next unsolicited "
00680 "scan\n", dev->name);
00681 }
00682 } else if (local->host_roaming == 2 &&
00683 local->iw_mode == IW_MODE_INFRA) {
00684 if (hostap_join_ap(dev))
00685 return -EINVAL;
00686 } else {
00687 printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only "
00688 "in Managed mode when host_roaming is enabled\n",
00689 dev->name);
00690 }
00691
00692 return 0;
00693 #endif
00694 }
00695
00696 static int prism2_ioctl_giwap(struct net_device *dev,
00697 struct iw_request_info *info,
00698 struct sockaddr *ap_addr, char *extra)
00699 {
00700 struct hostap_interface *iface = dev->priv;
00701 local_info_t *local = iface->local;
00702
00703 if (dev == local->stadev) {
00704 memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN);
00705 ap_addr->sa_family = ARPHRD_ETHER;
00706 return 0;
00707 }
00708
00709 if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID,
00710 &ap_addr->sa_data, ETH_ALEN, 1) < 0)
00711 return -EOPNOTSUPP;
00712
00713
00714
00715 memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN);
00716 ap_addr->sa_family = ARPHRD_ETHER;
00717
00718 return 0;
00719 }
00720
00721
00722 static int prism2_ioctl_siwnickn(struct net_device *dev,
00723 struct iw_request_info *info,
00724 struct iw_point *data, char *nickname)
00725 {
00726 struct hostap_interface *iface = dev->priv;
00727 local_info_t *local = iface->local;
00728
00729 memset(local->name, 0, sizeof(local->name));
00730 memcpy(local->name, nickname, data->length);
00731 local->name_set = 1;
00732
00733 if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) ||
00734 local->func->reset_port(dev))
00735 return -EINVAL;
00736
00737 return 0;
00738 }
00739
00740 static int prism2_ioctl_giwnickn(struct net_device *dev,
00741 struct iw_request_info *info,
00742 struct iw_point *data, char *nickname)
00743 {
00744 struct hostap_interface *iface = dev->priv;
00745 local_info_t *local = iface->local;
00746 int len;
00747 char name[MAX_NAME_LEN + 3];
00748 u16 val;
00749
00750 len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME,
00751 &name, MAX_NAME_LEN + 2, 0);
00752 val = __le16_to_cpu(*(u16 *) name);
00753 if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN)
00754 return -EOPNOTSUPP;
00755
00756 name[val + 2] = '\0';
00757 data->length = val + 1;
00758 memcpy(nickname, name + 2, val + 1);
00759
00760 return 0;
00761 }
00762
00763
00764 static int prism2_ioctl_siwfreq(struct net_device *dev,
00765 struct iw_request_info *info,
00766 struct iw_freq *freq, char *extra)
00767 {
00768 struct hostap_interface *iface = dev->priv;
00769 local_info_t *local = iface->local;
00770
00771
00772 if (freq->e == 1 &&
00773 freq->m / 100000 >= freq_list[0] &&
00774 freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) {
00775 int ch;
00776 int fr = freq->m / 100000;
00777 for (ch = 0; ch < FREQ_COUNT; ch++) {
00778 if (fr == freq_list[ch]) {
00779 freq->e = 0;
00780 freq->m = ch + 1;
00781 break;
00782 }
00783 }
00784 }
00785
00786 if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT ||
00787 !(local->channel_mask & (1 << (freq->m - 1))))
00788 return -EINVAL;
00789
00790 local->channel = freq->m;
00791 if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) ||
00792 local->func->reset_port(dev))
00793 return -EINVAL;
00794
00795 return 0;
00796 }
00797
00798 static int prism2_ioctl_giwfreq(struct net_device *dev,
00799 struct iw_request_info *info,
00800 struct iw_freq *freq, char *extra)
00801 {
00802 struct hostap_interface *iface = dev->priv;
00803 local_info_t *local = iface->local;
00804 u16 val;
00805
00806 if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) <
00807 0)
00808 return -EINVAL;
00809
00810 le16_to_cpus(&val);
00811 if (val < 1 || val > FREQ_COUNT)
00812 return -EINVAL;
00813
00814 freq->m = freq_list[val - 1] * 100000;
00815 freq->e = 1;
00816
00817 return 0;
00818 }
00819
00820 #ifndef ARPHRD_IEEE80211_RADIOTAP
00821 #define ARPHRD_IEEE80211_RADIOTAP 803
00822 #endif
00823
00824
00825 static void hostap_monitor_set_type(local_info_t *local)
00826 {
00827 struct net_device *dev = local->dev;
00828
00829 if (local->monitor_type == PRISM2_MONITOR_PRISM ||
00830 local->monitor_type == PRISM2_MONITOR_CAPHDR) {
00831 dev->type = ARPHRD_IEEE80211_RADIOTAP;
00832 dev->hard_header_parse =
00833 hostap_80211_prism_header_parse;
00834 } else {
00835 dev->type = ARPHRD_IEEE80211;
00836 dev->hard_header_parse = hostap_80211_header_parse;
00837 }
00838 }
00839
00840
00841 static int prism2_ioctl_siwessid(struct net_device *dev,
00842 struct iw_request_info *info,
00843 struct iw_point *data, char *ssid)
00844 {
00845 struct hostap_interface *iface = dev->priv;
00846 local_info_t *local = iface->local;
00847
00848 if (data->flags == 0)
00849 ssid[0] = '\0';
00850
00851 if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') {
00852
00853
00854 printk(KERN_DEBUG "%s: Host AP mode does not support "
00855 "'Any' essid\n", dev->name);
00856 return -EINVAL;
00857 }
00858
00859 memcpy(local->essid, ssid, data->length);
00860 local->essid[data->length] = '\0';
00861
00862 if ((!local->fw_ap &&
00863 hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid))
00864 || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) ||
00865 local->func->reset_port(dev))
00866 return -EINVAL;
00867
00868 return 0;
00869 }
00870
00871 static int prism2_ioctl_giwessid(struct net_device *dev,
00872 struct iw_request_info *info,
00873 struct iw_point *data, char *essid)
00874 {
00875 struct hostap_interface *iface = dev->priv;
00876 local_info_t *local = iface->local;
00877 u16 val;
00878
00879 data->flags = 1;
00880 if (local->iw_mode == IW_MODE_MASTER) {
00881 data->length = strlen(local->essid);
00882 memcpy(essid, local->essid, IW_ESSID_MAX_SIZE);
00883 } else {
00884 int len;
00885 char ssid[MAX_SSID_LEN + 2];
00886 memset(ssid, 0, sizeof(ssid));
00887 len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID,
00888 &ssid, MAX_SSID_LEN + 2, 0);
00889 val = __le16_to_cpu(*(u16 *) ssid);
00890 if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) {
00891 return -EOPNOTSUPP;
00892 }
00893 data->length = val;
00894 memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE);
00895 }
00896
00897 return 0;
00898 }
00899
00900
00901 static int prism2_ioctl_giwrange(struct net_device *dev,
00902 struct iw_request_info *info,
00903 struct iw_point *data, char *extra)
00904 {
00905 struct hostap_interface *iface = dev->priv;
00906 local_info_t *local = iface->local;
00907 struct iw_range *range = (struct iw_range *) extra;
00908 u8 rates[10];
00909 u16 val;
00910 int i, len, over2;
00911
00912 data->length = sizeof(struct iw_range);
00913 memset(range, 0, sizeof(struct iw_range));
00914
00915 #if WIRELESS_EXT > 9
00916
00917
00918
00919 range->txpower_capa = IW_TXPOW_DBM;
00920
00921 if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC)
00922 {
00923 range->min_pmp = 1 * 1024;
00924 range->max_pmp = 65535 * 1024;
00925 range->min_pmt = 1 * 1024;
00926 range->max_pmt = 1000 * 1024;
00927 range->pmp_flags = IW_POWER_PERIOD;
00928 range->pmt_flags = IW_POWER_TIMEOUT;
00929 range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT |
00930 IW_POWER_UNICAST_R | IW_POWER_ALL_R;
00931 }
00932 #endif
00933
00934 #if WIRELESS_EXT > 10
00935 range->we_version_compiled = WIRELESS_EXT;
00936 range->we_version_source = 13;
00937
00938 range->retry_capa = IW_RETRY_LIMIT;
00939 range->retry_flags = IW_RETRY_LIMIT;
00940 range->min_retry = 0;
00941 range->max_retry = 255;
00942 #endif
00943
00944 range->num_channels = FREQ_COUNT;
00945
00946 val = 0;
00947 for (i = 0; i < FREQ_COUNT; i++) {
00948 if (local->channel_mask & (1 << i)) {
00949 range->freq[val].i = i + 1;
00950 range->freq[val].m = freq_list[i] * 100000;
00951 range->freq[val].e = 1;
00952 val++;
00953 }
00954 if (val == IW_MAX_FREQUENCIES)
00955 break;
00956 }
00957 range->num_frequency = val;
00958
00959 range->max_qual.qual = 92;
00960 range->max_qual.level = 154;
00961 range->max_qual.noise = 154;
00962 range->sensitivity = 3;
00963
00964 range->max_encoding_tokens = WEP_KEYS;
00965 range->num_encoding_sizes = 2;
00966 range->encoding_size[0] = 5;
00967 range->encoding_size[1] = 13;
00968
00969 over2 = 0;
00970 len = prism2_get_datarates(dev, rates);
00971 range->num_bitrates = 0;
00972 for (i = 0; i < len; i++) {
00973 if (range->num_bitrates < IW_MAX_BITRATES) {
00974 range->bitrate[range->num_bitrates] =
00975 rates[i] * 500000;
00976 range->num_bitrates++;
00977 }
00978 if (rates[i] == 0x0b || rates[i] == 0x16)
00979 over2 = 1;
00980 }
00981
00982 range->throughput = over2 ? 5500000 : 1500000;
00983
00984 range->min_rts = 0;
00985 range->max_rts = 2347;
00986 range->min_frag = 256;
00987 range->max_frag = 2346;
00988
00989 return 0;
00990 }
00991
00992
00993 static int hostap_monitor_mode_enable(local_info_t *local)
00994 {
00995 struct net_device *dev = local->dev;
00996
00997 printk(KERN_DEBUG "Enabling monitor mode\n");
00998 hostap_monitor_set_type(local);
00999
01000 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
01001 HFA384X_PORTTYPE_PSEUDO_IBSS)) {
01002 printk(KERN_DEBUG "Port type setting for monitor mode "
01003 "failed\n");
01004 return -EOPNOTSUPP;
01005 }
01006
01007
01008
01009
01010 if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS,
01011 HFA384X_WEPFLAGS_HOSTENCRYPT |
01012 HFA384X_WEPFLAGS_HOSTDECRYPT)) {
01013 printk(KERN_DEBUG "WEP flags setting failed\n");
01014 return -EOPNOTSUPP;
01015 }
01016
01017 if (local->func->reset_port(dev) ||
01018 local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01019 (HFA384X_TEST_MONITOR << 8),
01020 0, NULL, NULL)) {
01021 printk(KERN_DEBUG "Setting monitor mode failed\n");
01022 return -EOPNOTSUPP;
01023 }
01024
01025 return 0;
01026 }
01027
01028
01029 static int hostap_monitor_mode_disable(local_info_t *local)
01030 {
01031 struct net_device *dev = local->dev;
01032
01033 printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name);
01034 dev->type = ARPHRD_IEEE80211_RADIOTAP;
01035 dev->hard_header_parse = local->saved_eth_header_parse;
01036 if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01037 (HFA384X_TEST_STOP << 8),
01038 0, NULL, NULL))
01039 return -1;
01040 return hostap_set_encryption(local);
01041 }
01042
01043
01044 static int hostap_dssstest_mode_enable(local_info_t *local)
01045 {
01046 struct net_device *dev = local->dev;
01047
01048 if (!local->dev_enabled) {
01049 printk(KERN_DEBUG "%s: Device must be up for DSSS test mode\n",
01050 dev->name);
01051 return -ENETDOWN;
01052 }
01053
01054 printk(KERN_DEBUG "%s: Enabling DSSS test mode\n", dev->name);
01055
01056 if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01057 (HFA384X_TEST_XMIT << 8),
01058 0xAAAA, NULL, NULL)) {
01059 printk(KERN_DEBUG "%s: Setting DSSS-test mode failed\n",
01060 dev->name);
01061 return -EOPNOTSUPP;
01062 }
01063
01064 return 0;
01065 }
01066
01067
01068 static int hostap_dssstest_mode_disable(local_info_t *local)
01069 {
01070 struct net_device *dev = local->dev;
01071
01072 if (dev == NULL)
01073 return -1;
01074
01075 printk(KERN_DEBUG "%s: Disabling DSSS test mode.\n", dev->name);
01076
01077
01078 if (local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01079 (HFA384X_TEST_STOP << 8),
01080 0, NULL, NULL)) {
01081 printk(KERN_DEBUG "%s: Disable DSSS-test mode failed.\n",
01082 dev->name);
01083 return -1;
01084 }
01085
01086 return 0;
01087 }
01088
01089
01090 static int prism2_ioctl_siwmode(struct net_device *dev,
01091 struct iw_request_info *info,
01092 __u32 *mode, char *extra)
01093 {
01094 struct hostap_interface *iface = dev->priv;
01095 local_info_t *local = iface->local;
01096 int double_reset = 0;
01097
01098 if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA &&
01099 *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT &&
01100 *mode != IW_MODE_MONITOR)
01101 return -EOPNOTSUPP;
01102
01103 #ifdef PRISM2_NO_STATION_MODES
01104 if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA)
01105 return -EOPNOTSUPP;
01106 #endif
01107
01108 if (*mode == local->iw_mode)
01109 return 0;
01110
01111 if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') {
01112 printk(KERN_WARNING "%s: empty SSID not allowed in Master "
01113 "mode\n", dev->name);
01114 return -EINVAL;
01115 }
01116
01117 if (local->iw_mode == IW_MODE_MONITOR)
01118 hostap_monitor_mode_disable(local);
01119
01120 if (local->iw_mode == IW_MODE_ADHOC && *mode == IW_MODE_MASTER) {
01121
01122
01123
01124
01125 double_reset = 1;
01126 }
01127
01128 printk(KERN_DEBUG "prism2: %s: operating mode changed "
01129 "%d -> %d\n", dev->name, local->iw_mode, *mode);
01130 local->iw_mode = *mode;
01131
01132 if (local->iw_mode == IW_MODE_MONITOR)
01133 hostap_monitor_mode_enable(local);
01134 else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt &&
01135 !local->fw_encrypt_ok) {
01136 printk(KERN_DEBUG "%s: defaulting to host-based encryption as "
01137 "a workaround for firmware bug in Host AP mode WEP\n",
01138 dev->name);
01139 local->host_encrypt = 1;
01140 }
01141
01142 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
01143 hostap_get_porttype(local)))
01144 return -EOPNOTSUPP;
01145
01146 if (local->func->reset_port(dev))
01147 return -EINVAL;
01148 if (double_reset && local->func->reset_port(dev))
01149 return -EINVAL;
01150
01151 return 0;
01152 }
01153
01154
01155 static int prism2_ioctl_giwmode(struct net_device *dev,
01156 struct iw_request_info *info,
01157 __u32 *mode, char *extra)
01158 {
01159 struct hostap_interface *iface = dev->priv;
01160 local_info_t *local = iface->local;
01161
01162 if (dev == local->stadev) {
01163 *mode = IW_MODE_INFRA;
01164 return 0;
01165 }
01166
01167 *mode = local->iw_mode;
01168 return 0;
01169 }
01170
01171
01172 static int prism2_ioctl_siwpower(struct net_device *dev,
01173 struct iw_request_info *info,
01174 struct iw_param *wrq, char *extra)
01175 {
01176 #ifdef PRISM2_NO_STATION_MODES
01177 return -EOPNOTSUPP;
01178 #else
01179 int ret = 0;
01180
01181 if (wrq->disabled)
01182 return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0);
01183
01184 switch (wrq->flags & IW_POWER_MODE) {
01185 case IW_POWER_UNICAST_R:
01186 ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0);
01187 if (ret)
01188 return ret;
01189 ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
01190 if (ret)
01191 return ret;
01192 break;
01193 case IW_POWER_ALL_R:
01194 ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1);
01195 if (ret)
01196 return ret;
01197 ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
01198 if (ret)
01199 return ret;
01200 break;
01201 case IW_POWER_ON:
01202 break;
01203 default:
01204 return -EINVAL;
01205 }
01206
01207 if (wrq->flags & IW_POWER_TIMEOUT) {
01208 ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
01209 if (ret)
01210 return ret;
01211 ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION,
01212 wrq->value / 1024);
01213 if (ret)
01214 return ret;
01215 }
01216 if (wrq->flags & IW_POWER_PERIOD) {
01217 ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1);
01218 if (ret)
01219 return ret;
01220 ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
01221 wrq->value / 1024);
01222 if (ret)
01223 return ret;
01224 }
01225
01226 return ret;
01227 #endif
01228 }
01229
01230
01231 static int prism2_ioctl_giwpower(struct net_device *dev,
01232 struct iw_request_info *info,
01233 struct iw_param *rrq, char *extra)
01234 {
01235 #ifdef PRISM2_NO_STATION_MODES
01236 return -EOPNOTSUPP;
01237 #else
01238 struct hostap_interface *iface = dev->priv;
01239 local_info_t *local = iface->local;
01240 u16 enable, mcast;
01241
01242 if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1)
01243 < 0)
01244 return -EINVAL;
01245
01246 if (!__le16_to_cpu(enable)) {
01247 rrq->disabled = 1;
01248 return 0;
01249 }
01250
01251 rrq->disabled = 0;
01252
01253 if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
01254 u16 timeout;
01255 if (local->func->get_rid(dev,
01256 HFA384X_RID_CNFPMHOLDOVERDURATION,
01257 &timeout, 2, 1) < 0)
01258 return -EINVAL;
01259
01260 rrq->flags = IW_POWER_TIMEOUT;
01261 rrq->value = __le16_to_cpu(timeout) * 1024;
01262 } else {
01263 u16 period;
01264 if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION,
01265 &period, 2, 1) < 0)
01266 return -EINVAL;
01267
01268 rrq->flags = IW_POWER_PERIOD;
01269 rrq->value = __le16_to_cpu(period) * 1024;
01270 }
01271
01272 if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast,
01273 2, 1) < 0)
01274 return -EINVAL;
01275
01276 if (__le16_to_cpu(mcast))
01277 rrq->flags |= IW_POWER_ALL_R;
01278 else
01279 rrq->flags |= IW_POWER_UNICAST_R;
01280
01281 return 0;
01282 #endif
01283 }
01284
01285
01286 #if WIRELESS_EXT > 10
01287 static int prism2_ioctl_siwretry(struct net_device *dev,
01288 struct iw_request_info *info,
01289 struct iw_param *rrq, char *extra)
01290 {
01291 struct hostap_interface *iface = dev->priv;
01292 local_info_t *local = iface->local;
01293
01294 if (rrq->disabled)
01295 return -EINVAL;
01296
01297
01298
01299 if (rrq->flags == IW_RETRY_LIMIT) {
01300 if (rrq->value < 0) {
01301
01302
01303 local->manual_retry_count = -1;
01304 local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY;
01305 } else {
01306 if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT,
01307 rrq->value)) {
01308 printk(KERN_DEBUG "%s: Alternate retry count "
01309 "setting to %d failed\n",
01310 dev->name, rrq->value);
01311 return -EOPNOTSUPP;
01312 }
01313
01314 local->manual_retry_count = rrq->value;
01315 local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY;
01316 }
01317 return 0;
01318 }
01319
01320 return -EOPNOTSUPP;
01321
01322 #if 0
01323
01324
01325 if (rrq->flags & IW_RETRY_LIMIT) {
01326 if (rrq->flags & IW_RETRY_MAX)
01327 HFA384X_RID_LONGRETRYLIMIT = rrq->value;
01328 else if (rrq->flags & IW_RETRY_MIN)
01329 HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
01330 else {
01331 HFA384X_RID_LONGRETRYLIMIT = rrq->value;
01332 HFA384X_RID_SHORTRETRYLIMIT = rrq->value;
01333 }
01334
01335 }
01336
01337 if (rrq->flags & IW_RETRY_LIFETIME) {
01338 HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024;
01339 }
01340
01341 return 0;
01342 #endif
01343 }
01344
01345 static int prism2_ioctl_giwretry(struct net_device *dev,
01346 struct iw_request_info *info,
01347 struct iw_param *rrq, char *extra)
01348 {
01349 struct hostap_interface *iface = dev->priv;
01350 local_info_t *local = iface->local;
01351 u16 shortretry, longretry, lifetime, altretry;
01352
01353 if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry,
01354 2, 1) < 0 ||
01355 local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry,
01356 2, 1) < 0 ||
01357 local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME,
01358 &lifetime, 2, 1) < 0)
01359 return -EINVAL;
01360
01361 le16_to_cpus(&shortretry);
01362 le16_to_cpus(&longretry);
01363 le16_to_cpus(&lifetime);
01364
01365 rrq->disabled = 0;
01366
01367 if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) {
01368 rrq->flags = IW_RETRY_LIFETIME;
01369 rrq->value = lifetime * 1024;
01370 } else {
01371 if (local->manual_retry_count >= 0) {
01372 rrq->flags = IW_RETRY_LIMIT;
01373 if (local->func->get_rid(dev,
01374 HFA384X_RID_CNFALTRETRYCOUNT,
01375 &altretry, 2, 1) >= 0)
01376 rrq->value = le16_to_cpu(altretry);
01377 else
01378 rrq->value = local->manual_retry_count;
01379 } else if ((rrq->flags & IW_RETRY_MAX)) {
01380 rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
01381 rrq->value = longretry;
01382 } else {
01383 rrq->flags = IW_RETRY_LIMIT;
01384 rrq->value = shortretry;
01385 if (shortretry != longretry)
01386 rrq->flags |= IW_RETRY_MIN;
01387 }
01388 }
01389 return 0;
01390 }
01391 #endif
01392
01393
01394 #if WIRELESS_EXT > 9
01395
01396
01397
01398
01399
01400
01401
01402
01403 #ifdef RAW_TXPOWER_SETTING
01404
01405
01406
01407
01408
01409
01410
01411
01412 static int prism2_txpower_hfa386x_to_dBm(u16 val)
01413 {
01414 signed char tmp;
01415
01416 if (val > 255)
01417 val = 255;
01418
01419 tmp = val;
01420 tmp >>= 2;
01421
01422 return -12 - tmp;
01423 }
01424
01425 static u16 prism2_txpower_dBm_to_hfa386x(int val)
01426 {
01427 signed char tmp;
01428
01429 if (val > 20)
01430 return 128;
01431 else if (val < -43)
01432 return 127;
01433
01434 tmp = val;
01435 tmp = -12 - tmp;
01436 tmp <<= 2;
01437
01438 return (unsigned char) tmp;
01439 }
01440 #endif
01441
01442
01443 static int prism2_ioctl_siwtxpow(struct net_device *dev,
01444 struct iw_request_info *info,
01445 struct iw_param *rrq, char *extra)
01446 {
01447 struct hostap_interface *iface = dev->priv;
01448 local_info_t *local = iface->local;
01449 #ifdef RAW_TXPOWER_SETTING
01450 char *tmp;
01451 #endif
01452 u16 val;
01453 int ret = 0;
01454
01455 if (rrq->disabled) {
01456 if (local->txpower_type != PRISM2_TXPOWER_OFF) {
01457 val = 0xff;
01458 ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
01459 HFA386X_CR_A_D_TEST_MODES2,
01460 &val, NULL);
01461 printk(KERN_DEBUG "%s: Turning radio off: %s\n",
01462 dev->name, ret ? "failed" : "OK");
01463 local->txpower_type = PRISM2_TXPOWER_OFF;
01464 }
01465 return (ret ? -EOPNOTSUPP : 0);
01466 }
01467
01468 if (local->txpower_type == PRISM2_TXPOWER_OFF) {
01469 val = 0;
01470 ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
01471 HFA386X_CR_A_D_TEST_MODES2, &val, NULL);
01472 printk(KERN_DEBUG "%s: Turning radio on: %s\n",
01473 dev->name, ret ? "failed" : "OK");
01474 local->txpower_type = PRISM2_TXPOWER_UNKNOWN;
01475 }
01476
01477 #ifdef RAW_TXPOWER_SETTING
01478 if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) {
01479 printk(KERN_DEBUG "Setting ALC on\n");
01480 val = HFA384X_TEST_CFG_BIT_ALC;
01481 local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01482 (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL);
01483 local->txpower_type = PRISM2_TXPOWER_AUTO;
01484 return 0;
01485 }
01486
01487 if (local->txpower_type != PRISM2_TXPOWER_FIXED) {
01488 printk(KERN_DEBUG "Setting ALC off\n");
01489 val = HFA384X_TEST_CFG_BIT_ALC;
01490 local->func->cmd(dev, HFA384X_CMDCODE_TEST |
01491 (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL);
01492 local->txpower_type = PRISM2_TXPOWER_FIXED;
01493 }
01494
01495 if (rrq->flags == IW_TXPOW_DBM)
01496 tmp = "dBm";
01497 else if (rrq->flags == IW_TXPOW_MWATT)
01498 tmp = "mW";
01499 else
01500 tmp = "UNKNOWN";
01501 printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp);
01502
01503 if (rrq->flags != IW_TXPOW_DBM) {
01504 printk("SIOCSIWTXPOW with mW is not supported; use dBm\n");
01505 return -EOPNOTSUPP;
01506 }
01507
01508 local->txpower = rrq->value;
01509 val = prism2_txpower_dBm_to_hfa386x(local->txpower);
01510 if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
01511 HFA386X_CR_MANUAL_TX_POWER, &val, NULL))
01512 ret = -EOPNOTSUPP;
01513 #else
01514 if (rrq->fixed)
01515 ret = -EOPNOTSUPP;
01516 #endif
01517
01518 return ret;
01519 }
01520
01521 static int prism2_ioctl_giwtxpow(struct net_device *dev,
01522 struct iw_request_info *info,
01523 struct iw_param *rrq, char *extra)
01524 {
01525 #ifdef RAW_TXPOWER_SETTING
01526 struct hostap_interface *iface = dev->priv;
01527 local_info_t *local = iface->local;
01528 u16 resp0;
01529
01530 rrq->flags = IW_TXPOW_DBM;
01531 rrq->disabled = 0;
01532 rrq->fixed = 0;
01533
01534 if (local->txpower_type == PRISM2_TXPOWER_AUTO) {
01535 if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF,
01536 HFA386X_CR_MANUAL_TX_POWER,
01537 NULL, &resp0) == 0) {
01538 rrq->value = prism2_txpower_hfa386x_to_dBm(resp0);
01539 } else {
01540
01541 rrq->value = 15;
01542 }
01543 } else if (local->txpower_type == PRISM2_TXPOWER_OFF) {
01544 rrq->value = 0;
01545 rrq->disabled = 1;
01546 } else if (local->txpower_type == PRISM2_TXPOWER_FIXED) {
01547 rrq->value = local->txpower;
01548 rrq->fixed = 1;
01549 } else {
01550 printk("SIOCGIWTXPOW - unknown txpower_type=%d\n",
01551 local->txpower_type);
01552 }
01553 return 0;
01554 #else
01555 return -EOPNOTSUPP;
01556 #endif
01557 }
01558 #endif
01559
01560
01561 #if WIRELESS_EXT > 13
01562
01563 #ifndef PRISM2_NO_STATION_MODES
01564
01565
01566
01567
01568 static int prism2_request_hostscan(struct net_device *dev)
01569 {
01570 struct hostap_interface *iface = dev->priv;
01571 local_info_t *local = iface->local;
01572 struct hfa384x_hostscan_request scan_req;
01573
01574 memset(&scan_req, 0, sizeof(scan_req));
01575 scan_req.channel_list = __constant_cpu_to_le16(local->channel_mask);
01576 scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
01577
01578
01579 if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
01580 sizeof(scan_req))) {
01581 printk(KERN_DEBUG "%s: HOSTSCAN failed\n", dev->name);
01582 return -EINVAL;
01583 }
01584 return 0;
01585 }
01586
01587
01588 static int prism2_request_scan(struct net_device *dev)
01589 {
01590 struct hostap_interface *iface = dev->priv;
01591 local_info_t *local = iface->local;
01592 struct hfa384x_scan_request scan_req;
01593 int ret = 0;
01594
01595 memset(&scan_req, 0, sizeof(scan_req));
01596 scan_req.channel_list = __constant_cpu_to_le16(local->channel_mask);
01597 scan_req.txrate = __constant_cpu_to_le16(HFA384X_RATES_1MBPS);
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608 if (!local->host_roaming)
01609 hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
01610 HFA384X_ROAMING_HOST);
01611
01612 if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req,
01613 sizeof(scan_req))) {
01614 printk(KERN_DEBUG "SCANREQUEST failed\n");
01615 ret = -EINVAL;
01616 }
01617
01618 if (!local->host_roaming)
01619 hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE,
01620 HFA384X_ROAMING_FIRMWARE);
01621
01622 return 0;
01623 }
01624
01625 #else
01626
01627 static inline int prism2_request_hostscan(struct net_device *dev)
01628 {
01629 return -EOPNOTSUPP;
01630 }
01631
01632
01633 static inline int prism2_request_scan(struct net_device *dev)
01634 {
01635 return -EOPNOTSUPP;
01636 }
01637
01638 #endif
01639
01640
01641 static int prism2_ioctl_siwscan(struct net_device *dev,
01642 struct iw_request_info *info,
01643 struct iw_point *data, char *extra)
01644 {
01645 struct hostap_interface *iface = dev->priv;
01646 local_info_t *local = iface->local;
01647 int ret;
01648
01649 if (local->iw_mode == IW_MODE_MASTER) {
01650
01651
01652
01653 data->length = 0;
01654 return 0;
01655 }
01656
01657 if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1))
01658 ret = prism2_request_hostscan(dev);
01659 else
01660 ret = prism2_request_scan(dev);
01661
01662 if (ret == 0)
01663 local->scan_timestamp = jiffies;
01664
01665
01666
01667 return ret;
01668 }
01669
01670
01671 #ifndef PRISM2_NO_STATION_MODES
01672
01673
01674 static inline int prism2_translate_scan(local_info_t *local, char *buffer)
01675 {
01676 struct hfa384x_scan_result *scan;
01677 struct hfa384x_hostscan_result *hscan;
01678 int i, entries, entry, hostscan;
01679 struct iw_event iwe;
01680 char *current_ev = buffer;
01681 char *end_buf = buffer + IW_SCAN_MAX_DATA;
01682 char *current_val;
01683 u16 capabilities;
01684 u8 *pos;
01685
01686 spin_lock_bh(&local->lock);
01687
01688 hostscan = local->last_scan_type == PRISM2_HOSTSCAN;
01689 entries = hostscan ? local->last_hostscan_results_count :
01690 local->last_scan_results_count;
01691 for (entry = 0; entry < entries; entry++) {
01692 scan = &local->last_scan_results[entry];
01693 hscan = &local->last_hostscan_results[entry];
01694
01695
01696 memset(&iwe, 0, sizeof(iwe));
01697 iwe.cmd = SIOCGIWAP;
01698 iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
01699 memcpy(iwe.u.ap_addr.sa_data,
01700 hostscan ? hscan->bssid : scan->bssid, ETH_ALEN);
01701
01702
01703
01704
01705
01706
01707 iwe.len = IW_EV_ADDR_LEN;
01708 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
01709 IW_EV_ADDR_LEN);
01710
01711
01712
01713 memset(&iwe, 0, sizeof(iwe));
01714 iwe.cmd = SIOCGIWESSID;
01715 iwe.u.data.length = le16_to_cpu(hostscan ? hscan->ssid_len :
01716 scan->ssid_len);
01717 if (iwe.u.data.length > 32)
01718 iwe.u.data.length = 32;
01719 iwe.u.data.flags = 1;
01720 iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
01721 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
01722 hostscan ? hscan->ssid :
01723 scan->ssid);
01724
01725 memset(&iwe, 0, sizeof(iwe));
01726 iwe.cmd = SIOCGIWMODE;
01727 capabilities = le16_to_cpu(hostscan ? hscan->capability :
01728 scan->capability);
01729 if (capabilities & (WLAN_CAPABILITY_ESS |
01730 WLAN_CAPABILITY_IBSS)) {
01731 if (capabilities & WLAN_CAPABILITY_ESS)
01732 iwe.u.mode = IW_MODE_MASTER;
01733 else
01734 iwe.u.mode = IW_MODE_ADHOC;
01735 iwe.len = IW_EV_UINT_LEN;
01736 current_ev = iwe_stream_add_event(current_ev, end_buf,
01737 &iwe,
01738 IW_EV_UINT_LEN);
01739 }
01740
01741 memset(&iwe, 0, sizeof(iwe));
01742 iwe.cmd = SIOCGIWFREQ;
01743 iwe.u.freq.m = freq_list[le16_to_cpu(hostscan ? hscan->chid :
01744 scan->chid) - 1] * 100000;
01745 iwe.u.freq.e = 1;
01746 iwe.len = IW_EV_FREQ_LEN;
01747 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
01748 IW_EV_FREQ_LEN);
01749
01750 memset(&iwe, 0, sizeof(iwe));
01751 iwe.cmd = IWEVQUAL;
01752 if (hostscan) {
01753 iwe.u.qual.level = le16_to_cpu(hscan->sl);
01754 iwe.u.qual.noise = le16_to_cpu(hscan->anl);
01755 } else {
01756 iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(
01757 le16_to_cpu(scan->sl));
01758 iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(
01759 le16_to_cpu(scan->anl));
01760 }
01761 iwe.len = IW_EV_QUAL_LEN;
01762 current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe,
01763 IW_EV_QUAL_LEN);
01764
01765 memset(&iwe, 0, sizeof(iwe));
01766 iwe.cmd = SIOCGIWENCODE;
01767 if (capabilities & WLAN_CAPABILITY_PRIVACY)
01768 iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
01769 else
01770 iwe.u.data.flags = IW_ENCODE_DISABLED;
01771 iwe.u.data.length = 0;
01772 iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
01773 current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
01774 "");
01775
01776 memset(&iwe, 0, sizeof(iwe));
01777 iwe.cmd = SIOCGIWRATE;
01778 current_val = current_ev + IW_EV_LCP_LEN;
01779 pos = hostscan ? hscan->sup_rates : scan->sup_rates;
01780 for (i = 0; i < sizeof(scan->sup_rates); i++) {
01781 if (pos[i] == 0)
01782 break;
01783
01784 iwe.u.bitrate.value =
01785 ((pos[i] & 0x7f) * 500000);
01786 current_val = iwe_stream_add_value(
01787 current_ev, current_val, end_buf, &iwe,
01788 IW_EV_PARAM_LEN);
01789 }
01790
01791 if ((current_val - current_ev) > IW_EV_LCP_LEN)
01792 current_ev = current_val;
01793
01794 #if WIRELESS_EXT > 14
01795 {
01796 char buf[20];
01797 memset(&iwe, 0, sizeof(iwe));
01798 iwe.cmd = IWEVCUSTOM;
01799 sprintf(buf, "bcn_int=%d",
01800 le16_to_cpu(hostscan ? hscan->beacon_interval :
01801 scan->beacon_interval));
01802 iwe.u.data.length = strlen(buf);
01803 current_ev = iwe_stream_add_point(current_ev, end_buf,
01804 &iwe, buf);
01805
01806 memset(&iwe, 0, sizeof(iwe));
01807 iwe.cmd = IWEVCUSTOM;
01808 sprintf(buf, "resp_rate=%d",
01809 le16_to_cpu(hostscan ? hscan->rate :
01810 scan->rate));
01811 iwe.u.data.length = strlen(buf);
01812 current_ev = iwe_stream_add_point(current_ev, end_buf,
01813 &iwe, buf);
01814
01815 if (hostscan && (capabilities & WLAN_CAPABILITY_IBSS))
01816 {
01817 memset(&iwe, 0, sizeof(iwe));
01818 iwe.cmd = IWEVCUSTOM;
01819 sprintf(buf, "atim=%d",
01820 le16_to_cpu(hscan->atim));
01821 iwe.u.data.length = strlen(buf);
01822 current_ev = iwe_stream_add_point(
01823 current_ev, end_buf, &iwe, buf);
01824 }
01825 }
01826 #endif
01827
01828
01829
01830
01831
01832 }
01833
01834 spin_unlock_bh(&local->lock);
01835
01836 return current_ev - buffer;
01837 }
01838 #endif
01839
01840
01841 static inline int prism2_ioctl_giwscan_sta(struct net_device *dev,
01842 struct iw_request_info *info,
01843 struct iw_point *data, char *extra)
01844 {
01845 #ifdef PRISM2_NO_STATION_MODES
01846 return -EOPNOTSUPP;
01847 #else
01848 struct hostap_interface *iface = dev->priv;
01849 local_info_t *local = iface->local;
01850 int res;
01851
01852
01853
01854 if (local->scan_timestamp &&
01855 time_before(jiffies, local->scan_timestamp + 3 * HZ)) {
01856
01857
01858
01859
01860
01861
01862
01863
01864 return -EAGAIN;
01865 }
01866 local->scan_timestamp = 0;
01867
01868 res = prism2_translate_scan(local, extra);
01869
01870 if (res >= 0) {
01871 data->length = res;
01872 return 0;
01873 } else {
01874 data->length = 0;
01875 return res;
01876 }
01877 #endif
01878 }
01879
01880
01881 static int prism2_ioctl_giwscan(struct net_device *dev,
01882 struct iw_request_info *info,
01883 struct iw_point *data, char *extra)
01884 {
01885 struct hostap_interface *iface = dev->priv;
01886 local_info_t *local = iface->local;
01887 int res;
01888
01889 if (local->iw_mode == IW_MODE_MASTER) {
01890
01891
01892
01893
01894
01895
01896
01897
01898 res = prism2_ap_translate_scan(dev, extra);
01899 if (res >= 0) {
01900 printk(KERN_DEBUG "Scan result translation succeeded "
01901 "(length=%d)\n", res);
01902 data->length = res;
01903 return 0;
01904 } else {
01905 printk(KERN_DEBUG
01906 "Scan result translation failed (res=%d)\n",
01907 res);
01908 data->length = 0;
01909 return res;
01910 }
01911 } else {
01912
01913 return prism2_ioctl_giwscan_sta(dev, info, data, extra);
01914 }
01915 }
01916 #endif
01917
01918
01919 static const struct iw_priv_args prism2_priv[] = {
01920 { PRISM2_IOCTL_MONITOR,
01921 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" },
01922 { PRISM2_IOCTL_DSSSTEST,
01923 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dssstest" },
01924 { PRISM2_IOCTL_READMIF,
01925 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
01926 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" },
01927 { PRISM2_IOCTL_WRITEMIF,
01928 IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" },
01929 { PRISM2_IOCTL_RESET,
01930 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" },
01931 { PRISM2_IOCTL_INQUIRE,
01932 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" },
01933 { PRISM2_IOCTL_SET_RID_WORD,
01934 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" },
01935 { PRISM2_IOCTL_MACCMD,
01936 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" },
01937 #ifdef PRISM2_USE_WE_TYPE_ADDR
01938 { PRISM2_IOCTL_WDS_ADD,
01939 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" },
01940 { PRISM2_IOCTL_WDS_DEL,
01941 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" },
01942 { PRISM2_IOCTL_ADDMAC,
01943 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" },
01944 { PRISM2_IOCTL_DELMAC,
01945 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" },
01946 { PRISM2_IOCTL_KICKMAC,
01947 IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" },
01948 #else
01949 { PRISM2_IOCTL_WDS_ADD,
01950 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_add" },
01951 { PRISM2_IOCTL_WDS_DEL,
01952 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "wds_del" },
01953 { PRISM2_IOCTL_ADDMAC,
01954 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "addmac" },
01955 { PRISM2_IOCTL_DELMAC,
01956 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "delmac" },
01957 { PRISM2_IOCTL_KICKMAC,
01958 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 18, 0, "kickmac" },
01959 #endif
01960
01961 { PRISM2_IOCTL_PRISM2_PARAM,
01962 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" },
01963 #if WIRELESS_EXT >= 12
01964 { PRISM2_IOCTL_GET_PRISM2_PARAM,
01965 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
01966 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" },
01967 #ifdef PRISM2_USE_WE_SUB_IOCTLS
01968
01969 { PRISM2_IOCTL_PRISM2_PARAM,
01970 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" },
01971 { PRISM2_IOCTL_GET_PRISM2_PARAM,
01972 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" },
01973
01974 { PRISM2_PARAM_PTYPE,
01975 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ptype" },
01976 { PRISM2_PARAM_PTYPE,
01977 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getptype" },
01978 { PRISM2_PARAM_TXRATECTRL,
01979 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" },
01980 { PRISM2_PARAM_TXRATECTRL,
01981 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" },
01982 { PRISM2_PARAM_BEACON_INT,
01983 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" },
01984 { PRISM2_PARAM_BEACON_INT,
01985 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" },
01986 #ifndef PRISM2_NO_STATION_MODES
01987 { PRISM2_PARAM_PSEUDO_IBSS,
01988 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" },
01989 { PRISM2_PARAM_PSEUDO_IBSS,
01990 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" },
01991 #endif
01992 { PRISM2_PARAM_ALC,
01993 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" },
01994 { PRISM2_PARAM_ALC,
01995 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" },
01996 { PRISM2_PARAM_TXPOWER,
01997 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txpower" },
01998 { PRISM2_PARAM_TXPOWER,
01999 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getxpower" },
02000 { PRISM2_PARAM_DUMP,
02001 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" },
02002 { PRISM2_PARAM_DUMP,
02003 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" },
02004 { PRISM2_PARAM_OTHER_AP_POLICY,
02005 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" },
02006 { PRISM2_PARAM_OTHER_AP_POLICY,
02007 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" },
02008 { PRISM2_PARAM_AP_MAX_INACTIVITY,
02009 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" },
02010 { PRISM2_PARAM_AP_MAX_INACTIVITY,
02011 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" },
02012 { PRISM2_PARAM_AP_BRIDGE_PACKETS,
02013 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" },
02014 { PRISM2_PARAM_AP_BRIDGE_PACKETS,
02015 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" },
02016 { PRISM2_PARAM_DTIM_PERIOD,
02017 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" },
02018 { PRISM2_PARAM_DTIM_PERIOD,
02019 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" },
02020 { PRISM2_PARAM_AP_NULLFUNC_ACK,
02021 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" },
02022 { PRISM2_PARAM_AP_NULLFUNC_ACK,
02023 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" },
02024 { PRISM2_PARAM_MAX_WDS,
02025 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" },
02026 { PRISM2_PARAM_MAX_WDS,
02027 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" },
02028 { PRISM2_PARAM_AP_AUTOM_AP_WDS,
02029 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" },
02030 { PRISM2_PARAM_AP_AUTOM_AP_WDS,
02031 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" },
02032 { PRISM2_PARAM_AP_AUTH_ALGS,
02033 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" },
02034 { PRISM2_PARAM_AP_AUTH_ALGS,
02035 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" },
02036 { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
02037 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" },
02038 { PRISM2_PARAM_MONITOR_ALLOW_FCSERR,
02039 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" },
02040 { PRISM2_PARAM_HOST_ENCRYPT,
02041 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" },
02042 { PRISM2_PARAM_HOST_ENCRYPT,
02043 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" },
02044 { PRISM2_PARAM_HOST_DECRYPT,
02045 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" },
02046 { PRISM2_PARAM_HOST_DECRYPT,
02047 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" },
02048 { PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX,
02049 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_rx" },
02050 { PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX,
02051 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_rx" },
02052 { PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX,
02053 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "busmaster_tx" },
02054 { PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX,
02055 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbusmaster_tx" },
02056 #ifndef PRISM2_NO_STATION_MODES
02057 { PRISM2_PARAM_HOST_ROAMING,
02058 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" },
02059 { PRISM2_PARAM_HOST_ROAMING,
02060 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" },
02061 #endif
02062 { PRISM2_PARAM_BCRX_STA_KEY,
02063 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" },
02064 { PRISM2_PARAM_BCRX_STA_KEY,
02065 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" },
02066 { PRISM2_PARAM_IEEE_802_1X,
02067 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" },
02068 { PRISM2_PARAM_IEEE_802_1X,
02069 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" },
02070 { PRISM2_PARAM_ANTSEL_TX,
02071 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" },
02072 { PRISM2_PARAM_ANTSEL_TX,
02073 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" },
02074 { PRISM2_PARAM_ANTSEL_RX,
02075 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" },
02076 { PRISM2_PARAM_ANTSEL_RX,
02077 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" },
02078 { PRISM2_PARAM_MONITOR_TYPE,
02079 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" },
02080 { PRISM2_PARAM_MONITOR_TYPE,
02081 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" },
02082 { PRISM2_PARAM_WDS_TYPE,
02083 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" },
02084 { PRISM2_PARAM_WDS_TYPE,
02085 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" },
02086 { PRISM2_PARAM_HOSTSCAN,
02087 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" },
02088 { PRISM2_PARAM_HOSTSCAN,
02089 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" },
02090 { PRISM2_PARAM_AP_SCAN,
02091 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" },
02092 { PRISM2_PARAM_AP_SCAN,
02093 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" },
02094 { PRISM2_PARAM_ENH_SEC,
02095 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" },
02096 { PRISM2_PARAM_ENH_SEC,
02097 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" },
02098 #ifdef PRISM2_IO_DEBUG
02099 { PRISM2_PARAM_IO_DEBUG,
02100 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" },
02101 { PRISM2_PARAM_IO_DEBUG,
02102 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" },
02103 #endif
02104 { PRISM2_PARAM_BASIC_RATES,
02105 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" },
02106 { PRISM2_PARAM_BASIC_RATES,
02107 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" },
02108 { PRISM2_PARAM_OPER_RATES,
02109 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" },
02110 { PRISM2_PARAM_OPER_RATES,
02111 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" },
02112 { PRISM2_PARAM_HOSTAPD,
02113 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" },
02114 { PRISM2_PARAM_HOSTAPD,
02115 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" },
02116 { PRISM2_PARAM_TX_OK,
02117 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tx_ok" },
02118 { PRISM2_PARAM_TX_OK,
02119 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettx_ok" },
02120 { PRISM2_PARAM_TX_EX,
02121 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tx_ex" },
02122 { PRISM2_PARAM_TX_EX,
02123 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettx_ex" },
02124
02125
02126 #endif
02127 #endif
02128 };
02129
02130
02131 #if WIRELESS_EXT <= 12
02132 static int prism2_ioctl_giwpriv(struct net_device *dev, struct iw_point *data)
02133 {
02134
02135 if (!data->pointer ||
02136 verify_area(VERIFY_WRITE, data->pointer, sizeof(prism2_priv)))
02137 return -EINVAL;
02138
02139 data->length = sizeof(prism2_priv) / sizeof(prism2_priv[0]);
02140 if (copy_to_user(data->pointer, prism2_priv, sizeof(prism2_priv)))
02141 return -EINVAL;
02142 return 0;
02143 }
02144 #endif
02145
02146
02147 static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i)
02148 {
02149 struct hostap_interface *iface = dev->priv;
02150 local_info_t *local = iface->local;
02151
02152 if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL))
02153 return -EOPNOTSUPP;
02154
02155 return 0;
02156 }
02157
02158
02159 static int prism2_ioctl_priv_prism2_param(struct net_device *dev,
02160 struct iw_request_info *info,
02161 void *wrqu, char *extra)
02162 {
02163 struct hostap_interface *iface = dev->priv;
02164 local_info_t *local = iface->local;
02165 int *i = (int *) extra;
02166 int param = *i;
02167 int value = *(i + 1);
02168 int ret = 0;
02169 u16 val;
02170
02171 switch (param) {
02172 case PRISM2_PARAM_PTYPE:
02173 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, value)) {
02174 ret = -EOPNOTSUPP;
02175 break;
02176 }
02177
02178 if (local->func->reset_port(dev))
02179 ret = -EINVAL;
02180 break;
02181
02182 case PRISM2_PARAM_TXRATECTRL:
02183 local->fw_tx_rate_control = value;
02184 break;
02185
02186 case PRISM2_PARAM_BEACON_INT:
02187 if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) ||
02188 local->func->reset_port(dev))
02189 ret = -EINVAL;
02190 else
02191 local->beacon_int = value;
02192 break;
02193
02194 #ifndef PRISM2_NO_STATION_MODES
02195 case PRISM2_PARAM_PSEUDO_IBSS:
02196 if (value == local->pseudo_adhoc)
02197 break;
02198
02199 if (value != 0 && value != 1) {
02200 ret = -EINVAL;
02201 break;
02202 }
02203
02204 printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n",
02205 dev->name, local->pseudo_adhoc, value);
02206 local->pseudo_adhoc = value;
02207 if (local->iw_mode != IW_MODE_ADHOC)
02208 break;
02209
02210 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
02211 hostap_get_porttype(local))) {
02212 ret = -EOPNOTSUPP;
02213 break;
02214 }
02215
02216 if (local->func->reset_port(dev))
02217 ret = -EINVAL;
02218 break;
02219 #endif
02220
02221 case PRISM2_PARAM_ALC:
02222 printk(KERN_DEBUG "%s: %s ALC\n", dev->name,
02223 value == 0 ? "Disabling" : "Enabling");
02224 val = HFA384X_TEST_CFG_BIT_ALC;
02225 local->func->cmd(dev, HFA384X_CMDCODE_TEST |
02226 (HFA384X_TEST_CFG_BITS << 8),
02227 value == 0 ? 0 : 1, &val, NULL);
02228 break;
02229
02230 case PRISM2_PARAM_TXPOWER:
02231 val = value;
02232 if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF,
02233 HFA386X_CR_MANUAL_TX_POWER, &val, NULL))
02234 ret = -EOPNOTSUPP;
02235 break;
02236
02237 case PRISM2_PARAM_DUMP:
02238 local->frame_dump = value;
02239 break;
02240
02241 case PRISM2_PARAM_OTHER_AP_POLICY:
02242 if (value < 0 || value > 3) {
02243 ret = -EINVAL;
02244 break;
02245 }
02246 if (local->ap != NULL)
02247 local->ap->ap_policy = value;
02248 break;
02249
02250 case PRISM2_PARAM_AP_MAX_INACTIVITY:
02251 if (value < 0 || value > 7 * 24 * 60 * 60) {
02252 ret = -EINVAL;
02253 break;
02254 }
02255 if (local->ap != NULL)
02256 local->ap->max_inactivity = value * HZ;
02257 break;
02258
02259 case PRISM2_PARAM_AP_BRIDGE_PACKETS:
02260 if (local->ap != NULL)
02261 local->ap->bridge_packets = value;
02262 break;
02263
02264 case PRISM2_PARAM_DTIM_PERIOD:
02265 if (value < 0 || value > 65535) {
02266 ret = -EINVAL;
02267 break;
02268 }
02269 if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value)
02270 || local->func->reset_port(dev))
02271 ret = -EINVAL;
02272 else
02273 local->dtim_period = value;
02274 break;
02275
02276 case PRISM2_PARAM_AP_NULLFUNC_ACK:
02277 if (local->ap != NULL)
02278 local->ap->nullfunc_ack = value;
02279 break;
02280
02281 case PRISM2_PARAM_MAX_WDS:
02282 local->wds_max_connections = value;
02283 break;
02284
02285 case PRISM2_PARAM_AP_AUTOM_AP_WDS:
02286 if (local->ap != NULL) {
02287 if (!local->ap->autom_ap_wds && value) {
02288
02289 hostap_add_wds_links(local);
02290 }
02291 local->ap->autom_ap_wds = value;
02292 }
02293 break;
02294
02295 case PRISM2_PARAM_AP_AUTH_ALGS:
02296 local->auth_algs = value;
02297 if (hostap_set_auth_algs(local))
02298 ret = -EINVAL;
02299 break;
02300
02301 case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
02302 local->monitor_allow_fcserr = value;
02303 break;
02304
02305 case PRISM2_PARAM_TX_OK:
02306 if (value) {
02307 local->tx_control |= HFA384X_TX_CTRL_TX_OK;
02308 } else {
02309 local->tx_control &= ~HFA384X_TX_CTRL_TX_OK;
02310 }
02311 break;
02312
02313 case PRISM2_PARAM_TX_EX:
02314 if (value) {
02315 local->tx_control |= HFA384X_TX_CTRL_TX_EX;
02316 } else {
02317 local->tx_control &= ~HFA384X_TX_CTRL_TX_EX;
02318 }
02319 break;
02320
02321 case PRISM2_PARAM_HOST_ENCRYPT:
02322 local->host_encrypt = value;
02323 if (hostap_set_encryption(local) ||
02324 local->func->reset_port(dev))
02325 ret = -EINVAL;
02326 break;
02327
02328 case PRISM2_PARAM_HOST_DECRYPT:
02329 local->host_decrypt = value;
02330 if (hostap_set_encryption(local) ||
02331 local->func->reset_port(dev))
02332 ret = -EINVAL;
02333 break;
02334
02335 case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX:
02336 local->bus_master_threshold_rx = value;
02337 break;
02338
02339 case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX:
02340 local->bus_master_threshold_tx = value;
02341 break;
02342
02343 #ifndef PRISM2_NO_STATION_MODES
02344 case PRISM2_PARAM_HOST_ROAMING:
02345 if (value < 0 || value > 2) {
02346 ret = -EINVAL;
02347 break;
02348 }
02349 local->host_roaming = value;
02350 if (hostap_set_roaming(local) || local->func->reset_port(dev))
02351 ret = -EINVAL;
02352 break;
02353 #endif
02354
02355 case PRISM2_PARAM_BCRX_STA_KEY:
02356 local->bcrx_sta_key = value;
02357 break;
02358
02359 case PRISM2_PARAM_IEEE_802_1X:
02360 local->ieee_802_1x = value;
02361 break;
02362
02363 case PRISM2_PARAM_ANTSEL_TX:
02364 if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
02365 ret = -EINVAL;
02366 break;
02367 }
02368 local->antsel_tx = value;
02369 hostap_set_antsel(local);
02370 break;
02371
02372 case PRISM2_PARAM_ANTSEL_RX:
02373 if (value < 0 || value > HOSTAP_ANTSEL_HIGH) {
02374 ret = -EINVAL;
02375 break;
02376 }
02377 local->antsel_rx = value;
02378 hostap_set_antsel(local);
02379 break;
02380
02381 case PRISM2_PARAM_MONITOR_TYPE:
02382 if (value != PRISM2_MONITOR_80211 &&
02383 value != PRISM2_MONITOR_CAPHDR &&
02384 value != PRISM2_MONITOR_PRISM) {
02385 ret = -EINVAL;
02386 break;
02387 }
02388 local->monitor_type = value;
02389 if (local->iw_mode == IW_MODE_MONITOR)
02390 hostap_monitor_set_type(local);
02391 break;
02392
02393 case PRISM2_PARAM_WDS_TYPE:
02394 local->wds_type = value;
02395 break;
02396
02397 case PRISM2_PARAM_HOSTSCAN:
02398 {
02399 struct hfa384x_hostscan_request scan_req;
02400 u16 rate;
02401
02402 memset(&scan_req, 0, sizeof(scan_req));
02403 scan_req.channel_list = __constant_cpu_to_le16(0x3fff);
02404 switch (value) {
02405 case 1: rate = HFA384X_RATES_1MBPS; break;
02406 case 2: rate = HFA384X_RATES_2MBPS; break;
02407 case 3: rate = HFA384X_RATES_5MBPS; break;
02408 case 4: rate = HFA384X_RATES_11MBPS; break;
02409 default: rate = HFA384X_RATES_1MBPS; break;
02410 }
02411 scan_req.txrate = cpu_to_le16(rate);
02412
02413
02414 if (local->iw_mode == IW_MODE_MASTER) {
02415 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
02416 HFA384X_PORTTYPE_BSS) ||
02417 local->func->reset_port(dev))
02418 printk(KERN_DEBUG "Leaving Host AP mode "
02419 "for HostScan failed\n");
02420 }
02421
02422 if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req,
02423 sizeof(scan_req))) {
02424 printk(KERN_DEBUG "HOSTSCAN failed\n");
02425 ret = -EINVAL;
02426 }
02427 if (local->iw_mode == IW_MODE_MASTER) {
02428 wait_queue_t __wait;
02429 init_waitqueue_entry(&__wait, current);
02430 add_wait_queue(&local->hostscan_wq, &__wait);
02431 set_current_state(TASK_INTERRUPTIBLE);
02432 schedule_timeout(HZ);
02433 if (signal_pending(current))
02434 ret = -EINTR;
02435 set_current_state(TASK_RUNNING);
02436 remove_wait_queue(&local->hostscan_wq, &__wait);
02437
02438 if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE,
02439 HFA384X_PORTTYPE_HOSTAP) ||
02440 local->func->reset_port(dev))
02441 printk(KERN_DEBUG "Returning to Host AP mode "
02442 "after HostScan failed\n");
02443 }
02444 break;
02445 }
02446
02447 case PRISM2_PARAM_AP_SCAN:
02448 local->passive_scan_interval = value;
02449 if (timer_pending(&local->passive_scan_timer))
02450 del_timer(&local->passive_scan_timer);
02451 if (value > 0) {
02452 local->passive_scan_timer.expires = jiffies +
02453 local->passive_scan_interval * HZ;
02454 add_timer(&local->passive_scan_timer);
02455 }
02456 break;
02457
02458 case PRISM2_PARAM_ENH_SEC:
02459 if (value < 0 || value > 3) {
02460 ret = -EINVAL;
02461 break;
02462 }
02463 local->enh_sec = value;
02464 if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY,
02465 local->enh_sec) ||
02466 local->func->reset_port(dev)) {
02467 printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w "
02468 "1.6.3 or newer\n", dev->name);
02469 ret = -EOPNOTSUPP;
02470 }
02471 break;
02472
02473 #ifdef PRISM2_IO_DEBUG
02474 case PRISM2_PARAM_IO_DEBUG:
02475 local->io_debug_enabled = value;
02476 break;
02477 #endif
02478
02479 case PRISM2_PARAM_BASIC_RATES:
02480 if ((value & local->tx_rate_control) != value || value == 0) {
02481 printk(KERN_INFO "%s: invalid basic rate set - basic "
02482 "rates must be in supported rate set\n",
02483 dev->name);
02484 ret = -EINVAL;
02485 break;
02486 }
02487 local->basic_rates = value;
02488 if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES,
02489 local->basic_rates) ||
02490 local->func->reset_port(dev))
02491 ret = -EINVAL;
02492 break;
02493
02494 case PRISM2_PARAM_OPER_RATES:
02495 local->tx_rate_control = value;
02496 if (hostap_set_rate(dev))
02497 ret = -EINVAL;
02498 break;
02499
02500 case PRISM2_PARAM_HOSTAPD:
02501 ret = hostap_set_hostapd(local, value, 1);
02502 break;
02503
02504 default:
02505 printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n",
02506 dev->name, param);
02507 ret = -EOPNOTSUPP;
02508 break;
02509 }
02510
02511 return ret;
02512 }
02513
02514
02515 #if WIRELESS_EXT >= 12
02516 static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev,
02517 struct iw_request_info *info,
02518 void *wrqu, char *extra)
02519 {
02520 struct hostap_interface *iface = dev->priv;
02521 local_info_t *local = iface->local;
02522 int *param = (int *) extra;
02523 int ret = 0;
02524 u16 val;
02525
02526 switch (*param) {
02527 case PRISM2_PARAM_PTYPE:
02528 if (local->func->get_rid(dev, HFA384X_RID_CNFPORTTYPE,
02529 &val, 2, 1) < 0)
02530 ret = -EINVAL;
02531 else
02532 *param = le16_to_cpu(val);
02533 break;
02534
02535 case PRISM2_PARAM_TXRATECTRL:
02536 *param = local->fw_tx_rate_control;
02537 break;
02538
02539 case PRISM2_PARAM_BEACON_INT:
02540 *param = local->beacon_int;
02541 break;
02542
02543 case PRISM2_PARAM_PSEUDO_IBSS:
02544 *param = local->pseudo_adhoc;
02545 break;
02546
02547 case PRISM2_PARAM_ALC:
02548 ret = -EOPNOTSUPP;
02549 break;
02550
02551 case PRISM2_PARAM_TXPOWER:
02552 if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF,
02553 HFA386X_CR_MANUAL_TX_POWER, NULL, &val))
02554 ret = -EOPNOTSUPP;
02555 *param = val;
02556 break;
02557
02558 case PRISM2_PARAM_DUMP:
02559 *param = local->frame_dump;
02560 break;
02561
02562 case PRISM2_PARAM_OTHER_AP_POLICY:
02563 if (local->ap != NULL)
02564 *param = local->ap->ap_policy;
02565 else
02566 ret = -EOPNOTSUPP;
02567 break;
02568
02569 case PRISM2_PARAM_AP_MAX_INACTIVITY:
02570 if (local->ap != NULL)
02571 *param = local->ap->max_inactivity / HZ;
02572 else
02573 ret = -EOPNOTSUPP;
02574 break;
02575
02576 case PRISM2_PARAM_AP_BRIDGE_PACKETS:
02577 if (local->ap != NULL)
02578 *param = local->ap->bridge_packets;
02579 else
02580 ret = -EOPNOTSUPP;
02581 break;
02582
02583 case PRISM2_PARAM_DTIM_PERIOD:
02584 *param = local->dtim_period;
02585 break;
02586
02587 case PRISM2_PARAM_AP_NULLFUNC_ACK:
02588 if (local->ap != NULL)
02589 *param = local->ap->nullfunc_ack;
02590 else
02591 ret = -EOPNOTSUPP;
02592 break;
02593
02594 case PRISM2_PARAM_MAX_WDS:
02595 *param = local->wds_max_connections;
02596 break;
02597
02598 case PRISM2_PARAM_AP_AUTOM_AP_WDS:
02599 if (local->ap != NULL)
02600 *param = local->ap->autom_ap_wds;
02601 else
02602 ret = -EOPNOTSUPP;
02603 break;
02604
02605 case PRISM2_PARAM_AP_AUTH_ALGS:
02606 *param = local->auth_algs;
02607 break;
02608
02609 case PRISM2_PARAM_MONITOR_ALLOW_FCSERR:
02610 *param = local->monitor_allow_fcserr;
02611 break;
02612
02613 case PRISM2_PARAM_TX_OK:
02614 *param = (local->tx_control & HFA384X_TX_CTRL_TX_OK)
02615 ? 1 : 0;
02616 break;
02617
02618 case PRISM2_PARAM_TX_EX:
02619 *param = (local->tx_control & HFA384X_TX_CTRL_TX_EX)
02620 ? 1 : 0;
02621 break;
02622
02623 case PRISM2_PARAM_HOST_ENCRYPT:
02624 *param = local->host_encrypt;
02625 break;
02626
02627 case PRISM2_PARAM_HOST_DECRYPT:
02628 *param = local->host_decrypt;
02629 break;
02630
02631 case PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX:
02632 *param = local->bus_master_threshold_rx;
02633 break;
02634
02635 case PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX:
02636 *param = local->bus_master_threshold_tx;
02637 break;
02638
02639 case PRISM2_PARAM_HOST_ROAMING:
02640 *param = local->host_roaming;
02641 break;
02642
02643 case PRISM2_PARAM_BCRX_STA_KEY:
02644 *param = local->bcrx_sta_key;
02645 break;
02646
02647 case PRISM2_PARAM_IEEE_802_1X:
02648 *param = local->ieee_802_1x;
02649 break;
02650
02651 case PRISM2_PARAM_ANTSEL_TX:
02652 *param = local->antsel_tx;
02653 break;
02654
02655 case PRISM2_PARAM_ANTSEL_RX:
02656 *param = local->antsel_rx;
02657 break;
02658
02659 case PRISM2_PARAM_MONITOR_TYPE:
02660 *param = local->monitor_type;
02661 break;
02662
02663 case PRISM2_PARAM_WDS_TYPE:
02664 *param = local->wds_type;
02665 break;
02666
02667 case PRISM2_PARAM_HOSTSCAN:
02668 ret = -EOPNOTSUPP;
02669 break;
02670
02671 case PRISM2_PARAM_AP_SCAN:
02672 *param = local->passive_scan_interval;
02673 break;
02674
02675 case PRISM2_PARAM_ENH_SEC:
02676 *param = local->enh_sec;
02677 break;
02678
02679 #ifdef PRISM2_IO_DEBUG
02680 case PRISM2_PARAM_IO_DEBUG:
02681 *param = local->io_debug_enabled;
02682 break;
02683 #endif
02684
02685 case PRISM2_PARAM_BASIC_RATES:
02686 *param = local->basic_rates;
02687 break;
02688
02689 case PRISM2_PARAM_OPER_RATES:
02690 *param = local->tx_rate_control;
02691 break;
02692
02693 case PRISM2_PARAM_HOSTAPD:
02694 *param = local->hostapd;
02695 break;
02696
02697 default:
02698 printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n",
02699 dev->name, *param);
02700 ret = -EOPNOTSUPP;
02701 break;
02702 }
02703
02704 return ret;
02705 }
02706 #endif
02707
02708
02709 static int prism2_ioctl_priv_readmif(struct net_device *dev,
02710 struct iw_request_info *info,
02711 void *wrqu, char *extra)
02712 {
02713 struct hostap_interface *iface = dev->priv;
02714 local_info_t *local = iface->local;
02715 u16 resp0;
02716
02717 if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL,
02718 &resp0))
02719 return -EOPNOTSUPP;
02720 else
02721 *extra = resp0;
02722
02723 return 0;
02724 }
02725
02726
02727 static int prism2_ioctl_priv_writemif(struct net_device *dev,
02728 struct iw_request_info *info,
02729 void *wrqu, char *extra)
02730 {
02731 struct hostap_interface *iface = dev->priv;
02732 local_info_t *local = iface->local;
02733 u16 cr, val;
02734
02735 cr = *extra;
02736 val = *(extra + 1);
02737 if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL))
02738 return -EOPNOTSUPP;
02739
02740 return 0;
02741 }
02742
02743
02744 static int prism2_ioctl_priv_dssstest(struct net_device *dev, int *i)
02745 {
02746 struct hostap_interface *iface = dev->priv;
02747 local_info_t *local = iface->local;
02748 int ret = 0;
02749
02750 if (*i == 0) {
02751 ret = hostap_dssstest_mode_disable(local);
02752 } else if (*i == 1) {
02753 ret = hostap_dssstest_mode_enable(local);
02754 } else
02755 ret = -EINVAL;
02756
02757 return ret;
02758
02759 }
02760
02761 static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i)
02762 {
02763 struct hostap_interface *iface = dev->priv;
02764 local_info_t *local = iface->local;
02765 int ret = 0;
02766 u32 mode;
02767
02768 printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor "
02769 "- update software to use iwconfig mode monitor\n",
02770 dev->name, current->pid, current->comm);
02771
02772
02773
02774 if (*i == 0) {
02775
02776
02777 mode = IW_MODE_MASTER;
02778 ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
02779 } else if (*i == 1) {
02780
02781
02782
02783
02784 ret = -EOPNOTSUPP;
02785 } else if (*i == 2 || *i == 3) {
02786 switch (*i) {
02787 case 2:
02788 local->monitor_type = PRISM2_MONITOR_80211;
02789 break;
02790 case 3:
02791 local->monitor_type = PRISM2_MONITOR_PRISM;
02792 break;
02793 }
02794 mode = IW_MODE_MONITOR;
02795 ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL);
02796 hostap_monitor_mode_enable(local);
02797 } else
02798 ret = -EINVAL;
02799
02800 return ret;
02801 }
02802
02803
02804 static int prism2_ioctl_priv_reset(struct net_device *dev, int *i)
02805 {
02806 struct hostap_interface *iface = dev->priv;
02807 local_info_t *local = iface->local;
02808
02809 printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i);
02810 switch (*i) {
02811 case 0:
02812
02813 local->func->hw_shutdown(dev, 1);
02814 local->func->hw_config(dev, 0);
02815 break;
02816
02817 case 1:
02818
02819 local->func->hw_reset(dev);
02820 break;
02821
02822 case 2:
02823
02824 local->func->reset_port(dev);
02825 break;
02826
02827 case 3:
02828 if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL,
02829 NULL))
02830 return -EINVAL;
02831 break;
02832
02833 case 4:
02834 if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL,
02835 NULL))
02836 return -EINVAL;
02837 break;
02838
02839 default:
02840 printk(KERN_DEBUG "Unknown reset request %d\n", *i);
02841 return -EOPNOTSUPP;
02842 }
02843
02844 return 0;
02845 }
02846
02847
02848 #ifndef PRISM2_USE_WE_TYPE_ADDR
02849 static inline int hex2int(char c)
02850 {
02851 if (c >= '0' && c <= '9')
02852 return (c - '0');
02853 if (c >= 'a' && c <= 'f')
02854 return (c - 'a' + 10);
02855 if (c >= 'A' && c <= 'F')
02856 return (c - 'A' + 10);
02857 return -1;
02858 }
02859
02860 static int macstr2addr(char *macstr, u8 *addr)
02861 {
02862 int i, val, val2;
02863 char *pos = macstr;
02864
02865 for (i = 0; i < 6; i++) {
02866 val = hex2int(*pos++);
02867 if (val < 0)
02868 return -1;
02869 val2 = hex2int(*pos++);
02870 if (val2 < 0)
02871 return -1;
02872 addr[i] = (val * 16 + val2) & 0xff;
02873
02874 if (i < 5 && *pos++ != ':')
02875 return -1;
02876 }
02877
02878 return 0;
02879 }
02880
02881
02882 static int prism2_ioctl_priv_wds(struct net_device *dev, int add, char *macstr)
02883 {
02884 struct hostap_interface *iface = dev->priv;
02885 local_info_t *local = iface->local;
02886 u8 addr[6];
02887
02888 if (macstr2addr(macstr, addr)) {
02889 printk(KERN_DEBUG "Invalid MAC address\n");
02890 return -EINVAL;
02891 }
02892
02893 if (add)
02894 return prism2_wds_add(local, addr, 1);
02895 else
02896 return prism2_wds_del(local, addr, 1, 0);
02897 }
02898 #endif
02899
02900
02901 static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i)
02902 {
02903 int rid = *i;
02904 int value = *(i + 1);
02905
02906 printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value);
02907
02908 if (hostap_set_word(dev, rid, value))
02909 return -EINVAL;
02910
02911 return 0;
02912 }
02913
02914
02915 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
02916 static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd)
02917 {
02918 int ret = 0;
02919
02920 switch (*cmd) {
02921 case AP_MAC_CMD_POLICY_OPEN:
02922 local->ap->mac_restrictions.policy = MAC_POLICY_OPEN;
02923 break;
02924 case AP_MAC_CMD_POLICY_ALLOW:
02925 local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW;
02926 break;
02927 case AP_MAC_CMD_POLICY_DENY:
02928 local->ap->mac_restrictions.policy = MAC_POLICY_DENY;
02929 break;
02930 case AP_MAC_CMD_FLUSH:
02931 ap_control_flush_macs(&local->ap->mac_restrictions);
02932 break;
02933 case AP_MAC_CMD_KICKALL:
02934 ap_control_kickall(local->ap);
02935 hostap_deauth_all_stas(local->dev, local->ap, 0);
02936 break;
02937 default:
02938 ret = -EOPNOTSUPP;
02939 break;
02940 }
02941
02942 return ret;
02943 }
02944
02945
02946 enum { AP_CTRL_MAC_ADD, AP_CTRL_MAC_DEL, AP_CTRL_MAC_KICK };
02947
02948 #ifndef PRISM2_USE_WE_TYPE_ADDR
02949 static int ap_mac_ioctl(local_info_t *local, char *macstr, int cmd)
02950 {
02951 u8 addr[6];
02952
02953 if (macstr2addr(macstr, addr)) {
02954 printk(KERN_DEBUG "Invalid MAC address '%s'\n", macstr);
02955 return -EINVAL;
02956 }
02957
02958 switch (cmd) {
02959 case AP_CTRL_MAC_ADD:
02960 return ap_control_add_mac(&local->ap->mac_restrictions, addr);
02961 case AP_CTRL_MAC_DEL:
02962 return ap_control_del_mac(&local->ap->mac_restrictions, addr);
02963 case AP_CTRL_MAC_KICK:
02964 return ap_control_kick_mac(local->ap, local->dev, addr);
02965 default:
02966 return -EOPNOTSUPP;
02967 }
02968 }
02969 #endif
02970 #endif
02971
02972
02973 #ifdef PRISM2_DOWNLOAD_SUPPORT
02974 static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p)
02975 {
02976 struct prism2_download_param *param;
02977 int ret = 0;
02978
02979 if (p->length < sizeof(struct prism2_download_param) ||
02980 p->length > 1024 || !p->pointer)
02981 return -EINVAL;
02982
02983 param = (struct prism2_download_param *)
02984 kmalloc(p->length, GFP_KERNEL);
02985 if (param == NULL)
02986 return -ENOMEM;
02987
02988 if (copy_from_user(param, p->pointer, p->length)) {
02989 ret = -EFAULT;
02990 goto out;
02991 }
02992
02993 if (p->length < sizeof(struct prism2_download_param) +
02994 param->num_areas * sizeof(struct prism2_download_area)) {
02995 ret = -EINVAL;
02996 goto out;
02997 }
02998
02999 ret = local->func->download(local, param);
03000
03001 out:
03002 if (param != NULL)
03003 kfree(param);
03004
03005 return ret;
03006 }
03007 #endif
03008
03009
03010 static int prism2_ioctl_set_encryption(local_info_t *local,
03011 struct prism2_hostapd_param *param,
03012 int param_len)
03013 {
03014 int ret = 0;
03015 struct hostap_crypto_ops *ops;
03016 struct prism2_crypt_data **crypt;
03017 void *sta_ptr;
03018
03019 param->u.crypt.err = 0;
03020 param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0';
03021
03022 if (param_len !=
03023 (int) ((char *) param->u.crypt.key - (char *) param) +
03024 param->u.crypt.key_len)
03025 return -EINVAL;
03026
03027 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
03028 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
03029 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
03030 sta_ptr = NULL;
03031 crypt = &local->crypt;
03032 } else {
03033 sta_ptr = ap_crypt_get_ptrs(
03034 local->ap, param->sta_addr,
03035 (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT),
03036 &crypt);
03037
03038 if (sta_ptr == NULL) {
03039 param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
03040 return -EINVAL;
03041 }
03042 }
03043
03044 if (strcmp(param->u.crypt.alg, "none") == 0) {
03045 prism2_crypt_delayed_deinit(local, crypt);
03046 goto done;
03047 }
03048
03049 ops = hostap_get_crypto_ops(param->u.crypt.alg);
03050 if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
03051 request_module("hostap_crypt_wep");
03052 ops = hostap_get_crypto_ops(param->u.crypt.alg);
03053 }
03054 if (ops == NULL) {
03055 printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n",
03056 local->dev->name, param->u.crypt.alg);
03057 param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG;
03058 ret = -EINVAL;
03059 goto done;
03060 }
03061
03062
03063
03064 local->host_decrypt = local->host_encrypt = 1;
03065
03066 if (*crypt == NULL || (*crypt)->ops != ops) {
03067 struct prism2_crypt_data *new_crypt;
03068
03069 prism2_crypt_delayed_deinit(local, crypt);
03070
03071 new_crypt = (struct prism2_crypt_data *)
03072 kmalloc(sizeof(struct prism2_crypt_data), GFP_KERNEL);
03073 if (new_crypt == NULL) {
03074 ret = -ENOMEM;
03075 goto done;
03076 }
03077 memset(new_crypt, 0, sizeof(struct prism2_crypt_data));
03078 new_crypt->ops = ops;
03079 new_crypt->priv = new_crypt->ops->init();
03080 if (new_crypt->priv == NULL) {
03081 kfree(new_crypt);
03082 param->u.crypt.err =
03083 HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED;
03084 ret = -EINVAL;
03085 goto done;
03086 }
03087
03088 *crypt = new_crypt;
03089 }
03090
03091 if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) ||
03092 param->u.crypt.key_len > 0) && (*crypt)->ops->set_key &&
03093 (*crypt)->ops->set_key(param->u.crypt.idx, param->u.crypt.key,
03094 param->u.crypt.key_len, (*crypt)->priv) < 0) {
03095 printk(KERN_DEBUG "%s: key setting failed\n",
03096 local->dev->name);
03097 param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED;
03098 ret = -EINVAL;
03099 goto done;
03100 }
03101
03102 if ((param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) &&
03103 (*crypt)->ops->set_key_idx &&
03104 (*crypt)->ops->set_key_idx(param->u.crypt.idx, (*crypt)->priv) < 0)
03105 {
03106 printk(KERN_DEBUG "%s: TX key idx setting failed\n",
03107 local->dev->name);
03108 param->u.crypt.err = HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED;
03109 ret = -EINVAL;
03110 goto done;
03111 }
03112
03113 done:
03114 if (sta_ptr)
03115 hostap_handle_sta_release(sta_ptr);
03116
03117 if (ret == 0 &&
03118 (hostap_set_encryption(local) ||
03119 local->func->reset_port(local->dev))) {
03120 param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED;
03121 return -EINVAL;
03122 }
03123
03124 return ret;
03125 }
03126
03127
03128 static int prism2_ioctl_get_encryption(local_info_t *local,
03129 struct prism2_hostapd_param *param,
03130 int param_len)
03131 {
03132 struct prism2_crypt_data **crypt;
03133 void *sta_ptr;
03134 int max_key_len;
03135
03136 param->u.crypt.err = 0;
03137
03138 max_key_len = param_len -
03139 (int) ((char *) param->u.crypt.key - (char *) param);
03140 if (max_key_len < 0)
03141 return -EINVAL;
03142
03143 if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff &&
03144 param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff &&
03145 param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) {
03146 sta_ptr = NULL;
03147 crypt = &local->crypt;
03148 } else {
03149 sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0,
03150 &crypt);
03151
03152 if (sta_ptr == NULL) {
03153 param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR;
03154 return -EINVAL;
03155 }
03156 }
03157
03158 if (*crypt == NULL || (*crypt)->ops == NULL) {
03159 memcpy(param->u.crypt.alg, "none", 5);
03160 param->u.crypt.key_len = 0;
03161 param->u.crypt.idx = 0xff;
03162 } else {
03163 strncpy(param->u.crypt.alg, (*crypt)->ops->name,
03164 HOSTAP_CRYPT_ALG_NAME_LEN);
03165 param->u.crypt.key_len = 0;
03166 if (param->u.crypt.idx >= WEP_KEYS &&
03167 (*crypt)->ops->get_key_idx)
03168 param->u.crypt.idx =
03169 (*crypt)->ops->get_key_idx((*crypt)->priv);
03170
03171 if (param->u.crypt.idx < WEP_KEYS && (*crypt)->ops->get_key)
03172 param->u.crypt.key_len =
03173 (*crypt)->ops->get_key(param->u.crypt.idx,
03174 param->u.crypt.key,
03175 max_key_len,
03176 (*crypt)->priv);
03177 }
03178
03179 if (sta_ptr)
03180 hostap_handle_sta_release(sta_ptr);
03181
03182 return 0;
03183 }
03184
03185
03186 static int prism2_ioctl_get_rid(local_info_t *local,
03187 struct prism2_hostapd_param *param,
03188 int param_len)
03189 {
03190 int max_len, res;
03191
03192 max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
03193 if (max_len < 0)
03194 return -EINVAL;
03195
03196 res = local->func->get_rid(local->dev, param->u.rid.rid,
03197 param->u.rid.data, param->u.rid.len, 0);
03198 if (res >= 0) {
03199 param->u.rid.len = res;
03200 return 0;
03201 }
03202
03203 return res;
03204 }
03205
03206
03207 static int prism2_ioctl_set_rid(local_info_t *local,
03208 struct prism2_hostapd_param *param,
03209 int param_len)
03210 {
03211 int max_len;
03212
03213 max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN;
03214 if (max_len < 0 || max_len < param->u.rid.len)
03215 return -EINVAL;
03216
03217 return local->func->set_rid(local->dev, param->u.rid.rid,
03218 param->u.rid.data, param->u.rid.len);
03219 }
03220
03221
03222 static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local,
03223 struct prism2_hostapd_param *param,
03224 int param_len)
03225 {
03226 printk(KERN_DEBUG "%ssta: associated as client with AP " MACSTR "\n",
03227 local->dev->name, MAC2STR(param->sta_addr));
03228 memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN);
03229 return 0;
03230 }
03231
03232
03233 static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p)
03234 {
03235 struct prism2_hostapd_param *param;
03236 int ret = 0;
03237 int ap_ioctl = 0;
03238
03239 if (p->length < sizeof(struct prism2_hostapd_param) ||
03240 p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer)
03241 return -EINVAL;
03242
03243 param = (struct prism2_hostapd_param *) kmalloc(p->length, GFP_KERNEL);
03244 if (param == NULL)
03245 return -ENOMEM;
03246
03247 if (copy_from_user(param, p->pointer, p->length)) {
03248 ret = -EFAULT;
03249 goto out;
03250 }
03251
03252 switch (param->cmd) {
03253 case PRISM2_SET_ENCRYPTION:
03254 ret = prism2_ioctl_set_encryption(local, param, p->length);
03255 break;
03256 case PRISM2_GET_ENCRYPTION:
03257 ret = prism2_ioctl_get_encryption(local, param, p->length);
03258 break;
03259 case PRISM2_HOSTAPD_GET_RID:
03260 ret = prism2_ioctl_get_rid(local, param, p->length);
03261 break;
03262 case PRISM2_HOSTAPD_SET_RID:
03263 ret = prism2_ioctl_set_rid(local, param, p->length);
03264 break;
03265 case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR:
03266 ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length);
03267 break;
03268 default:
03269 ret = prism2_hostapd(local->ap, param);
03270 ap_ioctl = 1;
03271 break;
03272 }
03273
03274 if (ret == 1 || !ap_ioctl) {
03275 if (copy_to_user(p->pointer, param, p->length)) {
03276 ret = -EFAULT;
03277 goto out;
03278 } else if (ap_ioctl)
03279 ret = 0;
03280 }
03281
03282 out:
03283 if (param != NULL)
03284 kfree(param);
03285
03286 return ret;
03287 }
03288
03289
03290 #if WIRELESS_EXT > 12
03291
03292
03293 static const iw_handler prism2_handler[] =
03294 {
03295 (iw_handler) NULL,
03296 (iw_handler) prism2_get_name,
03297 (iw_handler) NULL,
03298 (iw_handler) NULL,
03299 (iw_handler) prism2_ioctl_siwfreq,
03300 (iw_handler) prism2_ioctl_giwfreq,
03301 (iw_handler) prism2_ioctl_siwmode,
03302 (iw_handler) prism2_ioctl_giwmode,
03303 (iw_handler) prism2_ioctl_siwsens,
03304 (iw_handler) prism2_ioctl_giwsens,
03305 (iw_handler) NULL ,
03306 (iw_handler) prism2_ioctl_giwrange,
03307 (iw_handler) NULL ,
03308 (iw_handler) NULL ,
03309 (iw_handler) NULL ,
03310 (iw_handler) NULL ,
03311 #if WIRELESS_EXT > 15
03312 iw_handler_set_spy,
03313 iw_handler_get_spy,
03314 iw_handler_set_thrspy,
03315 iw_handler_get_thrspy,
03316 #else
03317 (iw_handler) NULL,
03318 (iw_handler) prism2_ioctl_giwspy,
03319 (iw_handler) NULL,
03320 (iw_handler) NULL,
03321 #endif
03322 (iw_handler) prism2_ioctl_siwap,
03323 (iw_handler) prism2_ioctl_giwap,
03324 (iw_handler) NULL,
03325 (iw_handler) prism2_ioctl_giwaplist,
03326 #if WIRELESS_EXT > 13
03327 (iw_handler) prism2_ioctl_siwscan,
03328 (iw_handler) prism2_ioctl_giwscan,
03329 #else
03330 (iw_handler) NULL,
03331 (iw_handler) NULL,
03332 #endif
03333 (iw_handler) prism2_ioctl_siwessid,
03334 (iw_handler) prism2_ioctl_giwessid,
03335 (iw_handler) prism2_ioctl_siwnickn,
03336 (iw_handler) prism2_ioctl_giwnickn,
03337 (iw_handler) NULL,
03338 (iw_handler) NULL,
03339 (iw_handler) prism2_ioctl_siwrate,
03340 (iw_handler) prism2_ioctl_giwrate,
03341 (iw_handler) prism2_ioctl_siwrts,
03342 (iw_handler) prism2_ioctl_giwrts,
03343 (iw_handler) prism2_ioctl_siwfrag,
03344 (iw_handler) prism2_ioctl_giwfrag,
03345 (iw_handler) prism2_ioctl_siwtxpow,
03346 (iw_handler) prism2_ioctl_giwtxpow,
03347 (iw_handler) prism2_ioctl_siwretry,
03348 (iw_handler) prism2_ioctl_giwretry,
03349 (iw_handler) prism2_ioctl_siwencode,
03350 (iw_handler) prism2_ioctl_giwencode,
03351 (iw_handler) prism2_ioctl_siwpower,
03352 (iw_handler) prism2_ioctl_giwpower,
03353 };
03354
03355 static const iw_handler prism2_private_handler[] =
03356 {
03357 (iw_handler) prism2_ioctl_priv_prism2_param,
03358 (iw_handler) prism2_ioctl_priv_get_prism2_param,
03359 (iw_handler) prism2_ioctl_priv_writemif,
03360 (iw_handler) prism2_ioctl_priv_readmif,
03361 };
03362
03363 static const struct iw_handler_def hostap_iw_handler_def =
03364 {
03365 .num_standard = sizeof(prism2_handler) / sizeof(iw_handler),
03366 .num_private = sizeof(prism2_private_handler) / sizeof(iw_handler),
03367 .num_private_args = sizeof(prism2_priv) / sizeof(struct iw_priv_args),
03368 .standard = (iw_handler *) prism2_handler,
03369 .private = (iw_handler *) prism2_private_handler,
03370 .private_args = (struct iw_priv_args *) prism2_priv,
03371 #if WIRELESS_EXT > 15
03372 .spy_offset = offsetof(struct hostap_interface, spy_data),
03373 #endif
03374 };
03375 #endif
03376
03377
03378 int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
03379 {
03380 struct iwreq *wrq = (struct iwreq *) ifr;
03381 struct hostap_interface *iface = dev->priv;
03382 local_info_t *local = iface->local;
03383 int ret = 0;
03384
03385 switch (cmd) {
03386
03387 #if WIRELESS_EXT <= 12
03388 case SIOCGIWNAME:
03389 ret = prism2_get_name(dev, NULL, (char *) &wrq->u, NULL);
03390 break;
03391
03392 case SIOCSIWFREQ:
03393 ret = prism2_ioctl_siwfreq(dev, NULL, &wrq->u.freq, NULL);
03394 break;
03395 case SIOCGIWFREQ:
03396 ret = prism2_ioctl_giwfreq(dev, NULL, &wrq->u.freq, NULL);
03397 break;
03398
03399 case SIOCSIWAP:
03400 ret = prism2_ioctl_siwap(dev, NULL, &wrq->u.ap_addr, NULL);
03401 break;
03402 case SIOCGIWAP:
03403 ret = prism2_ioctl_giwap(dev, NULL, &wrq->u.ap_addr, NULL);
03404 break;
03405
03406 case SIOCSIWESSID:
03407 if (!wrq->u.essid.pointer)
03408 ret = -EINVAL;
03409 else if (wrq->u.essid.length > IW_ESSID_MAX_SIZE)
03410 ret = -E2BIG;
03411 else {
03412 char ssid[IW_ESSID_MAX_SIZE];
03413 if (copy_from_user(ssid, wrq->u.essid.pointer,
03414 wrq->u.essid.length)) {
03415 ret = -EFAULT;
03416 break;
03417 }
03418 ret = prism2_ioctl_siwessid(dev, NULL, &wrq->u.essid,
03419 ssid);
03420 }
03421 break;
03422 case SIOCGIWESSID:
03423 if (wrq->u.essid.length > IW_ESSID_MAX_SIZE)
03424 ret = -E2BIG;
03425 else if (wrq->u.essid.pointer) {
03426 char ssid[IW_ESSID_MAX_SIZE];
03427 ret = prism2_ioctl_giwessid(dev, NULL, &wrq->u.essid,
03428 ssid);
03429 if (copy_to_user(wrq->u.essid.pointer, ssid,
03430 wrq->u.essid.length))
03431 ret = -EFAULT;
03432 }
03433 break;
03434
03435 case SIOCSIWRATE:
03436 ret = prism2_ioctl_siwrate(dev, NULL, &wrq->u.bitrate, NULL);
03437 break;
03438 case SIOCGIWRATE:
03439 ret = prism2_ioctl_giwrate(dev, NULL, &wrq->u.bitrate, NULL);
03440 break;
03441
03442 case SIOCSIWRTS:
03443 ret = prism2_ioctl_siwrts(dev, NULL, &wrq->u.rts, NULL);
03444 break;
03445 case SIOCGIWRTS:
03446 ret = prism2_ioctl_giwrts(dev, NULL, &wrq->u.rts, NULL);
03447 break;
03448
03449 case SIOCSIWFRAG:
03450 ret = prism2_ioctl_siwfrag(dev, NULL, &wrq->u.rts, NULL);
03451 break;
03452 case SIOCGIWFRAG:
03453 ret = prism2_ioctl_giwfrag(dev, NULL, &wrq->u.rts, NULL);
03454 break;
03455
03456 case SIOCSIWENCODE:
03457 {
03458 char keybuf[WEP_KEY_LEN];
03459 if (wrq->u.encoding.pointer) {
03460 if (wrq->u.encoding.length > WEP_KEY_LEN) {
03461 ret = -E2BIG;
03462 break;
03463 }
03464 if (copy_from_user(keybuf,
03465 wrq->u.encoding.pointer,
03466 wrq->u.encoding.length)) {
03467 ret = -EFAULT;
03468 break;
03469 }
03470 } else if (wrq->u.encoding.length != 0) {
03471 ret = -EINVAL;
03472 break;
03473 }
03474 ret = prism2_ioctl_siwencode(dev, NULL,
03475 &wrq->u.encoding, keybuf);
03476 }
03477 break;
03478 case SIOCGIWENCODE:
03479 if (!capable(CAP_NET_ADMIN))
03480 ret = -EPERM;
03481 else if (wrq->u.encoding.pointer) {
03482 char keybuf[WEP_KEY_LEN];
03483 ret = prism2_ioctl_giwencode(dev, NULL,
03484 &wrq->u.encoding, keybuf);
03485 if (copy_to_user(wrq->u.encoding.pointer, keybuf,
03486 wrq->u.encoding.length))
03487 ret = -EFAULT;
03488 }
03489 break;
03490
03491 case SIOCSIWNICKN:
03492 if (wrq->u.essid.length > IW_ESSID_MAX_SIZE)
03493 ret = -E2BIG;
03494 else if (wrq->u.essid.pointer) {
03495 char nickbuf[IW_ESSID_MAX_SIZE + 1];
03496 if (copy_from_user(nickbuf, wrq->u.essid.pointer,
03497 wrq->u.essid.length)) {
03498 ret = -EFAULT;
03499 break;
03500 }
03501 ret = prism2_ioctl_siwnickn(dev, NULL, &wrq->u.essid,
03502 nickbuf);
03503 }
03504 break;
03505 case SIOCGIWNICKN:
03506 if (wrq->u.essid.pointer) {
03507 char nickbuf[IW_ESSID_MAX_SIZE + 1];
03508 ret = prism2_ioctl_giwnickn(dev, NULL, &wrq->u.essid,
03509 nickbuf);
03510 if (copy_to_user(wrq->u.essid.pointer, nickbuf,
03511 wrq->u.essid.length))
03512 ret = -EFAULT;
03513 }
03514 break;
03515
03516 case SIOCGIWSPY:
03517 {
03518 char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
03519 sizeof(struct iw_quality))];
03520 ret = prism2_ioctl_giwspy(dev, NULL, &wrq->u.data,
03521 buffer);
03522 if (ret == 0 && wrq->u.data.pointer &&
03523 copy_to_user(wrq->u.data.pointer, buffer,
03524 wrq->u.data.length *
03525 (sizeof(struct sockaddr) +
03526 sizeof(struct iw_quality))))
03527 ret = -EFAULT;
03528 }
03529 break;
03530
03531 case SIOCGIWRANGE:
03532 {
03533 struct iw_range range;
03534 ret = prism2_ioctl_giwrange(dev, NULL, &wrq->u.data,
03535 (char *) &range);
03536 if (copy_to_user(wrq->u.data.pointer, &range,
03537 sizeof(struct iw_range)))
03538 ret = -EFAULT;
03539 }
03540 break;
03541
03542 case SIOCSIWSENS:
03543 ret = prism2_ioctl_siwsens(dev, NULL, &wrq->u.sens, NULL);
03544 break;
03545 case SIOCGIWSENS:
03546 ret = prism2_ioctl_giwsens(dev, NULL, &wrq->u.sens, NULL);
03547 break;
03548
03549 case SIOCGIWAPLIST:
03550 if (wrq->u.data.pointer) {
03551 char buffer[IW_MAX_AP * (sizeof(struct sockaddr) +
03552 sizeof(struct iw_quality))];
03553 ret = prism2_ioctl_giwaplist(dev, NULL, &wrq->u.data,
03554 buffer);
03555 if (copy_to_user(wrq->u.data.pointer, buffer,
03556 (wrq->u.data.length *
03557 (sizeof(struct sockaddr) +
03558 sizeof(struct iw_quality)))))
03559 ret = -EFAULT;
03560 }
03561 break;
03562
03563 case SIOCSIWMODE:
03564 ret = prism2_ioctl_siwmode(dev, NULL, &wrq->u.mode, NULL);
03565 break;
03566 case SIOCGIWMODE:
03567 ret = prism2_ioctl_giwmode(dev, NULL, &wrq->u.mode, NULL);
03568 break;
03569
03570 case SIOCSIWPOWER:
03571 ret = prism2_ioctl_siwpower(dev, NULL, &wrq->u.power, NULL);
03572 break;
03573 case SIOCGIWPOWER:
03574 ret = prism2_ioctl_giwpower(dev, NULL, &wrq->u.power, NULL);
03575 break;
03576
03577 case SIOCGIWPRIV:
03578 ret = prism2_ioctl_giwpriv(dev, &wrq->u.data);
03579 break;
03580
03581 #if WIRELESS_EXT > 9
03582 case SIOCSIWTXPOW:
03583 ret = prism2_ioctl_siwtxpow(dev, NULL, &wrq->u.txpower, NULL);
03584 break;
03585 case SIOCGIWTXPOW:
03586 ret = prism2_ioctl_giwtxpow(dev, NULL, &wrq->u.txpower, NULL);
03587 break;
03588 #endif
03589
03590 #if WIRELESS_EXT > 10
03591 case SIOCSIWRETRY:
03592 ret = prism2_ioctl_siwretry(dev, NULL, &wrq->u.retry, NULL);
03593 break;
03594 case SIOCGIWRETRY:
03595 ret = prism2_ioctl_giwretry(dev, NULL, &wrq->u.retry, NULL);
03596 break;
03597 #endif
03598
03599
03600 case SIOCSIWNWID:
03601 case SIOCGIWNWID:
03602 ret = -EOPNOTSUPP;
03603 break;
03604
03605
03606 case SIOCSIWSPY:
03607 printk(KERN_DEBUG "%s unsupported WIRELESS_EXT ioctl(0x%04x)\n"
03608 , dev->name, cmd);
03609 ret = -EOPNOTSUPP;
03610 break;
03611
03612
03613
03614
03615
03616 case PRISM2_IOCTL_PRISM2_PARAM:
03617 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03618 else ret = prism2_ioctl_priv_prism2_param(dev, NULL, &wrq->u,
03619 (char *) &wrq->u);
03620 break;
03621 #if WIRELESS_EXT >= 12
03622 case PRISM2_IOCTL_GET_PRISM2_PARAM:
03623 ret = prism2_ioctl_priv_get_prism2_param(dev, NULL, &wrq->u,
03624 (char *) &wrq->u);
03625 break;
03626 #endif
03627
03628 case PRISM2_IOCTL_WRITEMIF:
03629 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03630 else ret = prism2_ioctl_priv_writemif(dev, NULL, &wrq->u,
03631 (char *) &wrq->u);
03632 break;
03633
03634 case PRISM2_IOCTL_READMIF:
03635 ret = prism2_ioctl_priv_readmif(dev, NULL, &wrq->u,
03636 (char *) &wrq->u);
03637 break;
03638
03639 #endif
03640
03641
03642
03643
03644
03645 case PRISM2_IOCTL_INQUIRE:
03646 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03647 else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name);
03648 break;
03649
03650 case PRISM2_IOCTL_MONITOR:
03651 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03652 else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name);
03653 break;
03654
03655 case PRISM2_IOCTL_DSSSTEST:
03656 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03657 else ret = prism2_ioctl_priv_dssstest(dev, (int *)
03658 wrq->u.name);
03659 break;
03660
03661 case PRISM2_IOCTL_RESET:
03662 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03663 else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name);
03664 break;
03665
03666 #ifdef PRISM2_USE_WE_TYPE_ADDR
03667 case PRISM2_IOCTL_WDS_ADD:
03668 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03669 else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1);
03670 break;
03671
03672 case PRISM2_IOCTL_WDS_DEL:
03673 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03674 else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0);
03675 break;
03676 #else
03677 case PRISM2_IOCTL_WDS_ADD:
03678 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03679 else if (wrq->u.data.pointer) {
03680 char addrbuf[18];
03681 if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) {
03682 ret = -EFAULT;
03683 break;
03684 }
03685 ret = prism2_ioctl_priv_wds(dev, 1, addrbuf);
03686 }
03687 break;
03688
03689 case PRISM2_IOCTL_WDS_DEL:
03690 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03691 else if (wrq->u.data.pointer) {
03692 char addrbuf[18];
03693 if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) {
03694 ret = -EFAULT;
03695 break;
03696 }
03697 ret = prism2_ioctl_priv_wds(dev, 0, addrbuf);
03698 }
03699 break;
03700 #endif
03701
03702 case PRISM2_IOCTL_SET_RID_WORD:
03703 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03704 else ret = prism2_ioctl_priv_set_rid_word(dev,
03705 (int *) wrq->u.name);
03706 break;
03707
03708 #ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT
03709 case PRISM2_IOCTL_MACCMD:
03710 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03711 else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name);
03712 break;
03713
03714 #ifdef PRISM2_USE_WE_TYPE_ADDR
03715 case PRISM2_IOCTL_ADDMAC:
03716 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03717 else ret = ap_control_add_mac(&local->ap->mac_restrictions,
03718 wrq->u.ap_addr.sa_data);
03719 break;
03720 case PRISM2_IOCTL_DELMAC:
03721 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03722 else ret = ap_control_del_mac(&local->ap->mac_restrictions,
03723 wrq->u.ap_addr.sa_data);
03724 break;
03725 case PRISM2_IOCTL_KICKMAC:
03726 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03727 else ret = ap_control_kick_mac(local->ap, local->dev,
03728 wrq->u.ap_addr.sa_data);
03729 break;
03730 #else
03731 case PRISM2_IOCTL_ADDMAC:
03732 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03733 else if (wrq->u.data.pointer) {
03734 char addrbuf[18];
03735 if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) {
03736 ret = -EFAULT;
03737 break;
03738 }
03739 ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_ADD);
03740 }
03741 break;
03742
03743 case PRISM2_IOCTL_DELMAC:
03744 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03745 else if (wrq->u.data.pointer) {
03746 char addrbuf[18];
03747 if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) {
03748 ret = -EFAULT;
03749 break;
03750 }
03751 ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_DEL);
03752 }
03753 break;
03754
03755 case PRISM2_IOCTL_KICKMAC:
03756 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03757 else if (wrq->u.data.pointer) {
03758 char addrbuf[18];
03759 if (copy_from_user(addrbuf, wrq->u.data.pointer, 18)) {
03760 ret = -EFAULT;
03761 break;
03762 }
03763 ret = ap_mac_ioctl(local, addrbuf, AP_CTRL_MAC_KICK);
03764 }
03765 break;
03766 #endif
03767 #endif
03768
03769
03770
03771
03772
03773 #ifdef PRISM2_DOWNLOAD_SUPPORT
03774 case PRISM2_IOCTL_DOWNLOAD:
03775 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03776 else ret = prism2_ioctl_priv_download(local, &wrq->u.data);
03777 break;
03778 #endif
03779
03780 case PRISM2_IOCTL_HOSTAPD:
03781 if (!capable(CAP_NET_ADMIN)) ret = -EPERM;
03782 else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data);
03783 break;
03784
03785 default:
03786 #if WIRELESS_EXT > 12
03787 if (cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) {
03788
03789
03790 ret = -EOPNOTSUPP;
03791 break;
03792 }
03793 #endif
03794 printk(KERN_DEBUG "%s unsupported ioctl(0x%04x)\n",
03795 dev->name, cmd);
03796 ret = -EOPNOTSUPP;
03797 break;
03798 }
03799
03800 return ret;
03801 }
03802
03803 #endif