⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zd1201.c

📁 底层驱动开发
💻 C
📖 第 1 页 / 共 4 页
字号:
}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 + -