/*===================================================== * CopyRight (C) 2007 Qualcomm Inc. All Rights Reserved. * * * This file is part of Express Card USB Driver * * $Id: *==================================================== */ #include #include #include #include #include #include #include #include "ft1000_usb.h" #include MODULE_DESCRIPTION("FT1000 EXPRESS CARD DRIVER"); MODULE_LICENSE("Dual MPL/GPL"); MODULE_SUPPORTED_DEVICE("QFT FT1000 Express Cards"); void *pFileStart; size_t FileLength; #define VENDOR_ID 0x1291 /* Qualcomm vendor id */ #define PRODUCT_ID 0x11 /* fake product id */ /* table of devices that work with this driver */ static struct usb_device_id id_table[] = { {USB_DEVICE(VENDOR_ID, PRODUCT_ID)}, {}, }; MODULE_DEVICE_TABLE(usb, id_table); static bool gPollingfailed = FALSE; int ft1000_poll_thread(void *arg) { int ret = STATUS_SUCCESS; while (!kthread_should_stop()) { msleep(10); if (!gPollingfailed) { ret = ft1000_poll(arg); if (ret != STATUS_SUCCESS) { DEBUG("ft1000_poll_thread: polling failed\n"); gPollingfailed = TRUE; } } } return STATUS_SUCCESS; } static int ft1000_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_host_interface *iface_desc; struct usb_endpoint_descriptor *endpoint; struct usb_device *dev; unsigned numaltsetting; int i, ret = 0, size; struct ft1000_device *ft1000dev; struct ft1000_info *pft1000info = NULL; const struct firmware *dsp_fw; ft1000dev = kmalloc(sizeof(struct ft1000_device), GFP_KERNEL); if (!ft1000dev) { printk(KERN_ERR "out of memory allocating device structure\n"); return 0; } memset(ft1000dev, 0, sizeof(*ft1000dev)); dev = interface_to_usbdev(interface); DEBUG("ft1000_probe: usb device descriptor info:\n"); DEBUG("ft1000_probe: number of configuration is %d\n", dev->descriptor.bNumConfigurations); ft1000dev->dev = dev; ft1000dev->status = 0; ft1000dev->net = NULL; ft1000dev->tx_urb = usb_alloc_urb(0, GFP_ATOMIC); ft1000dev->rx_urb = usb_alloc_urb(0, GFP_ATOMIC); DEBUG("ft1000_probe is called\n"); numaltsetting = interface->num_altsetting; DEBUG("ft1000_probe: number of alt settings is :%d\n", numaltsetting); iface_desc = interface->cur_altsetting; DEBUG("ft1000_probe: number of endpoints is %d\n", iface_desc->desc.bNumEndpoints); DEBUG("ft1000_probe: descriptor type is %d\n", iface_desc->desc.bDescriptorType); DEBUG("ft1000_probe: interface number is %d\n", iface_desc->desc.bInterfaceNumber); DEBUG("ft1000_probe: alternatesetting is %d\n", iface_desc->desc.bAlternateSetting); DEBUG("ft1000_probe: interface class is %d\n", iface_desc->desc.bInterfaceClass); DEBUG("ft1000_probe: control endpoint info:\n"); DEBUG("ft1000_probe: descriptor0 type -- %d\n", iface_desc->endpoint[0].desc.bmAttributes); DEBUG("ft1000_probe: descriptor1 type -- %d\n", iface_desc->endpoint[1].desc.bmAttributes); DEBUG("ft1000_probe: descriptor2 type -- %d\n", iface_desc->endpoint[2].desc.bmAttributes); for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { endpoint = (struct usb_endpoint_descriptor *)&iface_desc-> endpoint[i].desc; DEBUG("endpoint %d\n", i); DEBUG("bEndpointAddress=%x, bmAttributes=%x\n", endpoint->bEndpointAddress, endpoint->bmAttributes); if ((endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { ft1000dev->bulk_in_endpointAddr = endpoint->bEndpointAddress; DEBUG("ft1000_probe: in: %d\n", endpoint->bEndpointAddress); } if (!(endpoint->bEndpointAddress & USB_DIR_IN) && ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)) { ft1000dev->bulk_out_endpointAddr = endpoint->bEndpointAddress; DEBUG("ft1000_probe: out: %d\n", endpoint->bEndpointAddress); } } DEBUG("bulk_in=%d, bulk_out=%d\n", ft1000dev->bulk_in_endpointAddr, ft1000dev->bulk_out_endpointAddr); ret = request_firmware(&dsp_fw, "ft3000.img", &dev->dev); if (ret < 0) { printk(KERN_ERR "Error request_firmware().\n"); goto err_fw; } size = max_t(uint, dsp_fw->size, 4096); pFileStart = kmalloc(size, GFP_KERNEL); if (!pFileStart) { release_firmware(dsp_fw); ret = -ENOMEM; goto err_fw; } memcpy(pFileStart, dsp_fw->data, dsp_fw->size); FileLength = dsp_fw->size; release_firmware(dsp_fw); DEBUG("ft1000_probe: start downloading dsp image...\n"); ret = init_ft1000_netdev(ft1000dev); if (ret) goto err_load; pft1000info = netdev_priv(ft1000dev->net); DEBUG("In probe: pft1000info=%p\n", pft1000info); ret = dsp_reload(ft1000dev); if (ret) { printk(KERN_ERR "Problem with DSP image loading\n"); goto err_load; } gPollingfailed = FALSE; pft1000info->pPollThread = kthread_run(ft1000_poll_thread, ft1000dev, "ft1000_poll"); if (IS_ERR(pft1000info->pPollThread)) { ret = PTR_ERR(pft1000info->pPollThread); goto err_load; } msleep(500); while (!pft1000info->CardReady) { if (gPollingfailed) { ret = -EIO; goto err_thread; } msleep(100); DEBUG("ft1000_probe::Waiting for Card Ready\n"); } DEBUG("ft1000_probe::Card Ready!!!! Registering network device\n"); ret = reg_ft1000_netdev(ft1000dev, interface); if (ret) goto err_thread; ret = ft1000_init_proc(ft1000dev->net); if (ret) goto err_proc; pft1000info->NetDevRegDone = 1; return 0; err_proc: unregister_netdev(ft1000dev->net); free_netdev(ft1000dev->net); err_thread: kthread_stop(pft1000info->pPollThread); err_load: kfree(pFileStart); err_fw: kfree(ft1000dev); return ret; } static void ft1000_disconnect(struct usb_interface *interface) { struct ft1000_info *pft1000info; DEBUG("ft1000_disconnect is called\n"); pft1000info = (struct ft1000_info *) usb_get_intfdata(interface); DEBUG("In disconnect pft1000info=%p\n", pft1000info); if (pft1000info) { ft1000_cleanup_proc(pft1000info); if (pft1000info->pPollThread) kthread_stop(pft1000info->pPollThread); DEBUG("ft1000_disconnect: threads are terminated\n"); if (pft1000info->pFt1000Dev->net) { DEBUG("ft1000_disconnect: destroy char driver\n"); ft1000_destroy_dev(pft1000info->pFt1000Dev->net); unregister_netdev(pft1000info->pFt1000Dev->net); DEBUG ("ft1000_disconnect: network device unregisterd\n"); free_netdev(pft1000info->pFt1000Dev->net); } usb_free_urb(pft1000info->pFt1000Dev->rx_urb); usb_free_urb(pft1000info->pFt1000Dev->tx_urb); DEBUG("ft1000_disconnect: urb freed\n"); kfree(pft1000info->pFt1000Dev); } kfree(pFileStart); return; } static struct usb_driver ft1000_usb_driver = { .name = "ft1000usb", .probe = ft1000_probe, .disconnect = ft1000_disconnect, .id_table = id_table, }; static int __init usb_ft1000_init(void) { int ret = 0; DEBUG("Initialize and register the driver\n"); ret = usb_register(&ft1000_usb_driver); if (ret) err("usb_register failed. Error number %d", ret); return ret; } static void __exit usb_ft1000_exit(void) { DEBUG("Deregister the driver\n"); usb_deregister(&ft1000_usb_driver); } module_init(usb_ft1000_init); module_exit(usb_ft1000_exit);