📄 zd1201.c
字号:
}static int zd1201_get_encode(struct net_device *dev, struct iw_request_info *info, struct iw_point *erq, char *key){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short i; int err; if (zd->encode_enabled) erq->flags = IW_ENCODE_ENABLED; else erq->flags = IW_ENCODE_DISABLED; if (zd->encode_restricted) erq->flags |= IW_ENCODE_RESTRICTED; else erq->flags |= IW_ENCODE_OPEN; i = (erq->flags & IW_ENCODE_INDEX) -1; if (i == -1) { err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); if (err) return err; } if (i<0 || i>= ZD1201_NUMKEYS) return -EINVAL; erq->flags |= i+1; erq->length = zd->encode_keylen[i]; memcpy(key, zd->encode_keys[i], erq->length); return 0;}static int zd1201_set_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short enabled, duration, level; int err; enabled = vwrq->disabled ? 0 : 1; if (enabled) { if (vwrq->flags & IW_POWER_PERIOD) { duration = vwrq->value; err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, duration); if (err) return err; goto out; } if (vwrq->flags & IW_POWER_TIMEOUT) { err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); if (err) return err; level = vwrq->value * 4 / duration; if (level > 4) level = 4; if (level < 0) level = 0; err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, level); if (err) return err; goto out; } return -EINVAL; }out: err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); if (err) return err; return 0;}static int zd1201_get_power(struct net_device *dev, struct iw_request_info *info, struct iw_param *vwrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short enabled, level, duration; int err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); if (err) return err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); if (err) return err; err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); if (err) return err; vwrq->disabled = enabled ? 0 : 1; if (vwrq->flags & IW_POWER_TYPE) { if (vwrq->flags & IW_POWER_PERIOD) { vwrq->value = duration; vwrq->flags = IW_POWER_PERIOD; } else { vwrq->value = duration * level / 4; vwrq->flags = IW_POWER_TIMEOUT; } } if (vwrq->flags & IW_POWER_MODE) { if (enabled && level) vwrq->flags = IW_POWER_UNICAST_R; else vwrq->flags = IW_POWER_ALL_R; } return 0;}static const iw_handler zd1201_iw_handler[] ={ (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ (iw_handler) NULL, /* SIOCSIWNWID */ (iw_handler) NULL, /* SIOCGIWNWID */ (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ (iw_handler) NULL, /* SIOCSIWSENS */ (iw_handler) NULL, /* SIOCGIWSENS */ (iw_handler) NULL, /* SIOCSIWRANGE */ (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ (iw_handler) NULL, /* SIOCSIWPRIV */ (iw_handler) NULL, /* SIOCGIWPRIV */ (iw_handler) NULL, /* SIOCSIWSTATS */ (iw_handler) NULL, /* SIOCGIWSTATS */ (iw_handler) NULL, /* SIOCSIWSPY */ (iw_handler) NULL, /* SIOCGIWSPY */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* SIOCGIWAPLIST */ (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ (iw_handler) NULL, /* SIOCSIWNICKN */ (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) NULL, /* -- hole -- */ (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ (iw_handler) NULL, /* SIOCSIWTXPOW */ (iw_handler) NULL, /* SIOCGIWTXPOW */ (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */};static int zd1201_set_hostauth(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; int err; if (!zd->ap) return -EOPNOTSUPP; err = zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); if (err) return err; return 0;}static int zd1201_get_hostauth(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short hostauth; int err; if (!zd->ap) return -EOPNOTSUPP; err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); if (err) return err; rrq->value = hostauth; rrq->fixed = 1; return 0;}static int zd1201_auth_sta(struct net_device *dev, struct iw_request_info *info, struct sockaddr *sta, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; unsigned char buffer[10]; if (!zd->ap) return -EOPNOTSUPP; memcpy(buffer, sta->sa_data, ETH_ALEN); *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ *(short*)(buffer+8) = 0; return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1);}static int zd1201_set_maxassoc(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; int err; if (!zd->ap) return -EOPNOTSUPP; err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); if (err) return err; return 0;}static int zd1201_get_maxassoc(struct net_device *dev, struct iw_request_info *info, struct iw_param *rrq, char *extra){ struct zd1201 *zd = (struct zd1201 *)dev->priv; short maxassoc; int err; if (!zd->ap) return -EOPNOTSUPP; err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); if (err) return err; rrq->value = maxassoc; rrq->fixed = 1; return 0;}static const iw_handler zd1201_private_handler[] = { (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ (iw_handler) NULL, /* nothing to get */ (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */};static const struct iw_priv_args zd1201_private_args[] = { { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "sethostauth" }, { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "authstation" }, { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, IW_PRIV_TYPE_NONE, "setmaxassoc" }, { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" },};static const struct iw_handler_def zd1201_iw_handlers = { .num_standard = sizeof(zd1201_iw_handler)/sizeof(iw_handler), .num_private = sizeof(zd1201_private_handler)/sizeof(iw_handler), .num_private_args = sizeof(zd1201_private_args)/sizeof(struct iw_priv_args), .standard = (iw_handler *)zd1201_iw_handler, .private = (iw_handler *)zd1201_private_handler, .private_args = (struct iw_priv_args *) zd1201_private_args,};static int zd1201_probe(struct usb_interface *interface, const struct usb_device_id *id){ struct zd1201 *zd; struct usb_device *usb; int i, err; short porttype; char buf[IW_ESSID_MAX_SIZE+2]; usb = interface_to_usbdev(interface); zd = kmalloc(sizeof(struct zd1201), GFP_KERNEL); if (!zd) { return -ENOMEM; } memset(zd, 0, sizeof(struct zd1201)); zd->ap = ap; zd->usb = usb; zd->removed = 0; init_waitqueue_head(&zd->rxdataq); INIT_HLIST_HEAD(&zd->fraglist); err = zd1201_fw_upload(usb, zd->ap); if (err) { dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); goto err_zd; } zd->endp_in = 1; zd->endp_out = 1; zd->endp_out2 = 2; zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); if (!zd->rx_urb || !zd->tx_urb) goto err_zd; for(i = 0; i<100; i++) udelay(1000); err = zd1201_drvr_start(zd); if (err) goto err_zd; err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); if (err) goto err_start; err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); if (err) goto err_start; zd->dev = alloc_etherdev(0); if (!zd->dev) goto err_start; zd->dev->priv = zd; zd->dev->open = zd1201_net_open; zd->dev->stop = zd1201_net_stop; zd->dev->get_stats = zd1201_get_stats; zd->dev->get_wireless_stats = zd1201_get_wireless_stats; zd->dev->wireless_handlers = (struct iw_handler_def *)&zd1201_iw_handlers; zd->dev->hard_start_xmit = zd1201_hard_start_xmit; zd->dev->watchdog_timeo = ZD1201_TX_TIMEOUT; zd->dev->tx_timeout = zd1201_tx_timeout; zd->dev->set_multicast_list = zd1201_set_multicast; zd->dev->set_mac_address = zd1201_set_mac_address; strcpy(zd->dev->name, "wlan%d"); err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, zd->dev->dev_addr, zd->dev->addr_len); if (err) goto err_net; /* Set wildcard essid to match zd->essid */ *(__le16 *)buf = cpu_to_le16(0); err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, IW_ESSID_MAX_SIZE+2, 1); if (err) goto err_net; if (zd->ap) porttype = ZD1201_PORTTYPE_AP; else porttype = ZD1201_PORTTYPE_BSS; err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); if (err) goto err_net; err = register_netdev(zd->dev); if (err) goto err_net; dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", zd->dev->name); usb_set_intfdata(interface, zd); return 0;err_net: free_netdev(zd->dev);err_start: /* Leave the device in reset state */ zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);err_zd: if (zd->tx_urb) usb_free_urb(zd->tx_urb); if (zd->rx_urb) usb_free_urb(zd->rx_urb); kfree(zd); return err;}static void zd1201_disconnect(struct usb_interface *interface){ struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); struct hlist_node *node, *node2; struct zd1201_frag *frag; if (!zd) return; usb_set_intfdata(interface, NULL); if (zd->dev) { unregister_netdev(zd->dev); free_netdev(zd->dev); } hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { hlist_del_init(&frag->fnode); kfree_skb(frag->skb); kfree(frag); } if (zd->tx_urb) { usb_kill_urb(zd->tx_urb); usb_free_urb(zd->tx_urb); } if (zd->rx_urb) { usb_kill_urb(zd->rx_urb); usb_free_urb(zd->rx_urb); } kfree(zd);}#ifdef CONFIG_PMstatic int zd1201_suspend(struct usb_interface *interface, pm_message_t message){ struct zd1201 *zd = usb_get_intfdata(interface); netif_device_detach(zd->dev); zd->was_enabled = zd->mac_enabled; if (zd->was_enabled) return zd1201_disable(zd); else return 0;}static int zd1201_resume(struct usb_interface *interface){ struct zd1201 *zd = usb_get_intfdata(interface); if (!zd || !zd->dev) return -ENODEV; netif_device_attach(zd->dev); if (zd->was_enabled) return zd1201_enable(zd); else return 0;}#else#define zd1201_suspend NULL#define zd1201_resume NULL#endifstatic struct usb_driver zd1201_usb = { .owner = THIS_MODULE, .name = "zd1201", .probe = zd1201_probe, .disconnect = zd1201_disconnect, .id_table = zd1201_table, .suspend = zd1201_suspend, .resume = zd1201_resume,};static int __init zd1201_init(void){ return usb_register(&zd1201_usb);}static void __exit zd1201_cleanup(void){ usb_deregister(&zd1201_usb);}module_init(zd1201_init);module_exit(zd1201_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -