/* * Copyright (c) 2007-2008 Atheros Communications Inc. * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* */ /* Module Name : zdusb.c */ /* */ /* Abstract */ /* This module contains plug and play handling for USB device driver*/ /* */ /* NOTES */ /* Platform dependent. */ /* */ /************************************************************************/ #ifdef MODVERSIONS #include #endif #include #include #include "usbdrv.h" #include "zdusb.h" int zfLnxAllocAllUrbs(struct usbdrv_private *macp); void zfLnxFreeAllUrbs(struct usbdrv_private *macp); void zfLnxUnlinkAllUrbs(struct usbdrv_private *macp); MODULE_AUTHOR("Atheros Communications"); MODULE_DESCRIPTION("Atheros 802.11n Wireless LAN adapter"); MODULE_LICENSE("Dual BSD/GPL"); static const char driver_name[] = "Otus"; /* table of devices that work with this driver */ static struct usb_device_id zd1221_ids [] = { { USB_DEVICE(VENDOR_ATHR, PRODUCT_AR9170) }, { USB_DEVICE(VENDOR_DLINK, PRODUCT_DWA160A) }, { USB_DEVICE(0x0846, 0x9010) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, zd1221_ids); extern u8_t zfLnxInitSetup(struct net_device *dev, struct usbdrv_private *macp); extern int usbdrv_close(struct net_device *dev); extern u8_t zfLnxClearStructs(struct net_device *dev); extern int zfWdsClose(struct net_device *dev); extern int zfUnregisterWdsDev(struct net_device* parentDev, u16_t wdsId); extern int zfLnxVapClose(struct net_device *dev); extern int zfLnxUnregisterVapDev(struct net_device* parentDev, u16_t vapId); /* WDS */ extern struct zsWdsStruct wds[ZM_WDS_PORT_NUMBER]; /* VAP */ extern struct zsVapStruct vap[ZM_VAP_PORT_NUMBER]; static int zfLnxProbe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev(interface); struct net_device *net = NULL; struct usbdrv_private *macp = NULL; int vendor_id, product_id; int result = 0; usb_get_dev(dev); vendor_id = dev->descriptor.idVendor; product_id = dev->descriptor.idProduct; #ifdef HMAC_DEBUG printk(KERN_NOTICE "vendor_id = %04x\n", vendor_id); printk(KERN_NOTICE "product_id = %04x\n", product_id); if (dev->speed == USB_SPEED_HIGH) printk(KERN_NOTICE "USB 2.0 Host\n"); else printk(KERN_NOTICE "USB 1.1 Host\n"); #endif if (!(macp = kmalloc(sizeof(struct usbdrv_private), GFP_KERNEL))) { printk(KERN_ERR "out of memory allocating device structure\n"); result = -ENOMEM; goto fail; } /* Zero the memory */ memset(macp, 0, sizeof(struct usbdrv_private)); net = alloc_etherdev(0); if (net == NULL) { printk(KERN_ERR "zfLnxProbe: Not able to alloc etherdev struct\n"); result = -ENOMEM; goto fail1; } strcpy(net->name, "ath%d"); net->ml_priv = macp; //kernel 2.6 macp->udev = dev; macp->device = net; /* set up the endpoint information */ /* check out the endpoints */ macp->interface = interface; //init_waitqueue_head(&macp->regSet_wait); //init_waitqueue_head(&macp->iorwRsp_wait); //init_waitqueue_head(&macp->term_wait); if (!zfLnxAllocAllUrbs(macp)) { result = -ENOMEM; goto fail2; } if (!zfLnxInitSetup(net, macp)) { result = -EIO; goto fail3; } else { usb_set_intfdata(interface, macp); SET_NETDEV_DEV(net, &interface->dev); if (register_netdev(net) != 0) { usb_set_intfdata(interface, NULL); goto fail3; } } netif_carrier_off(net); goto done; fail3: zfLnxFreeAllUrbs(macp); fail2: free_netdev(net); //kernel 2.6 fail1: kfree(macp); fail: usb_put_dev(dev); macp = NULL; done: return result; } static void zfLnxDisconnect(struct usb_interface *interface) { struct usbdrv_private *macp = (struct usbdrv_private *) usb_get_intfdata(interface); printk(KERN_DEBUG "zfLnxDisconnect\n"); if (!macp) { printk(KERN_ERR "unregistering non-existant device\n"); return; } if (macp->driver_isolated) { if (macp->device->flags & IFF_UP) usbdrv_close(macp->device); } #if 0 /* Close WDS */ //zfWdsClose(wds[0].dev); /* Unregister WDS */ //zfUnregisterWdsDev(macp->device, 0); /* Close VAP */ zfLnxVapClose(vap[0].dev); /* Unregister VAP */ zfLnxUnregisterVapDev(macp->device, 0); #endif zfLnxClearStructs(macp->device); unregister_netdev(macp->device); usb_put_dev(interface_to_usbdev(interface)); //printk(KERN_ERR "3. zfLnxUnlinkAllUrbs\n"); //zfLnxUnlinkAllUrbs(macp); /* Free network interface */ free_netdev(macp->device); zfLnxFreeAllUrbs(macp); //zfLnxClearStructs(macp->device); kfree(macp); macp = NULL; usb_set_intfdata(interface, NULL); } static struct usb_driver zd1221_driver = { .name = driver_name, .probe = zfLnxProbe, .disconnect = zfLnxDisconnect, .id_table = zd1221_ids, }; int __init zfLnxIinit(void) { printk(KERN_NOTICE "%s - version %s\n", DRIVER_NAME, VERSIONID); return usb_register(&zd1221_driver); } void __exit zfLnxExit(void) { usb_deregister(&zd1221_driver); } module_init(zfLnxIinit); module_exit(zfLnxExit);