11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Driver for ST5481 USB ISDN modem 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author Frode Isaksen 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com> 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de> 7475be4d85a274d0961593db41cf85689db1d583cJoe Perches * 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference. 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 13475be4d85a274d0961593db41cf85689db1d583cJoe Perches/* 141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * TODO: 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * b layer1 delay? 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * hotplug / unregister issues 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * mod_inc/dec_use_count 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * unify parts of d/b channel usb handling 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * file header 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * avoid copy to isoc buffer? 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * improve usb delay? 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * merge l1 state machines? 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * clean up debug 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/usb.h> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "st5481.h" 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_DESCRIPTION("ISDN4Linux: driver for ST5481 USB ISDN adapter"); 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_AUTHOR("Frode Isaksen"); 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL"); 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int protocol = 2; /* EURO-ISDN Default */ 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(protocol, int, 0); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int number_of_leds = 2; /* 2 LEDs on the adpater default */ 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(number_of_leds, int, 0); 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HISAX_DEBUG 4461ffcafafb3d985e1ab8463be0187b421614775cKarsten Keilstatic int debug = 0; 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_param(debug, int, 0); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 4761ffcafafb3d985e1ab8463be0187b421614775cKarsten Keilint st5481_debug; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* ====================================================================== 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * registration/deregistration with the USB layer 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function will be called when the adapter is plugged 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * into the USB bus. 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int probe_st5481(struct usb_interface *intf, 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds const struct usb_device_id *id) 591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct usb_device *dev = interface_to_usbdev(intf); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct st5481_adapter *adapter; 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct hisax_b_if *b_if[2]; 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval, i; 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n", 66475be4d85a274d0961593db41cf85689db1d583cJoe Perches le16_to_cpu(dev->descriptor.idVendor), 67475be4d85a274d0961593db41cf85689db1d583cJoe Perches le16_to_cpu(dev->descriptor.idProduct), 68475be4d85a274d0961593db41cf85689db1d583cJoe Perches number_of_leds); 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7041f96935b4c41daea2c4dbbf137960375cf764c1Burman Yan adapter = kzalloc(sizeof(struct st5481_adapter), GFP_KERNEL); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!adapter) 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENOMEM; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->number_of_leds = number_of_leds; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->usb_dev = dev; 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hisax_d_if.owner = THIS_MODULE; 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hisax_d_if.ifc.priv = adapter; 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->hisax_d_if.ifc.l2l1 = st5481_d_l2l1; 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 2; i++) { 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->bcs[i].adapter = adapter; 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->bcs[i].channel = i; 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = st5481_setup_usb(adapter); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err; 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = st5481_setup_d(adapter); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_usb; 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = st5481_setup_b(&adapter->bcs[0]); 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_d; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = st5481_setup_b(&adapter->bcs[1]); 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto err_b; 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (i = 0; i < 2; i++) 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds b_if[i] = &adapter->bcs[i].b_if; 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 107ae2d990eede0ef5938c210d48a177c044258ecd8Alan Stern if (hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", 108475be4d85a274d0961593db41cf85689db1d583cJoe Perches protocol) != 0) 109ae2d990eede0ef5938c210d48a177c044258ecd8Alan Stern goto err_b1; 110ae2d990eede0ef5938c210d48a177c044258ecd8Alan Stern 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_start(adapter); 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_intfdata(intf, adapter); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 116475be4d85a274d0961593db41cf85689db1d583cJoe Percheserr_b1: 117ae2d990eede0ef5938c210d48a177c044258ecd8Alan Stern st5481_release_b(&adapter->bcs[1]); 118475be4d85a274d0961593db41cf85689db1d583cJoe Percheserr_b: 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_b(&adapter->bcs[0]); 120475be4d85a274d0961593db41cf85689db1d583cJoe Percheserr_d: 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_d(adapter); 122475be4d85a274d0961593db41cf85689db1d583cJoe Percheserr_usb: 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_usb(adapter); 124475be4d85a274d0961593db41cf85689db1d583cJoe Percheserr: 1255310cbce900094dce5df4a671b411e15319a75d4Julia Lawall kfree(adapter); 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EIO; 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This function will be called when the adapter is removed 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * from the USB bus. 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void disconnect_st5481(struct usb_interface *intf) 1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct st5481_adapter *adapter = usb_get_intfdata(intf); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 137475be4d85a274d0961593db41cf85689db1d583cJoe Perches DBG(1, ""); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_set_intfdata(intf, NULL); 1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!adapter) 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return; 142475be4d85a274d0961593db41cf85689db1d583cJoe Perches 1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_stop(adapter); 1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_b(&adapter->bcs[1]); 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_b(&adapter->bcs[0]); 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_d(adapter); 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds // we would actually better wait for completion of outstanding urbs 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds mdelay(2); 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_release_usb(adapter); 1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds hisax_unregister(&adapter->hisax_d_if); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(adapter); 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The last 4 bits in the Product Id is set with 4 pins on the chip. 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_device_id st5481_ids[] = { 160475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x0) }, 161475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x1) }, 162475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x2) }, 163475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x3) }, 164475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x4) }, 165475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x5) }, 166475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x6) }, 167475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x7) }, 168475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x8) }, 169475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0x9) }, 170475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xA) }, 171475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xB) }, 172475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xC) }, 173475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xD) }, 174475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xE) }, 175475be4d85a274d0961593db41cf85689db1d583cJoe Perches { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID + 0xF) }, 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds { } 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 178475be4d85a274d0961593db41cf85689db1d583cJoe PerchesMODULE_DEVICE_TABLE(usb, st5481_ids); 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct usb_driver st5481_usb_driver = { 1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .name = "st5481_usb", 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .probe = probe_st5481, 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .disconnect = disconnect_st5481, 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds .id_table = st5481_ids, 185e1f12eb6ba6f1e74007eb01ed26fad7c5239d62bSarah Sharp .disable_hub_initiated_lpm = 1, 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int __init st5481_usb_init(void) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retval; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_HISAX_DEBUG 1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_debug = debug; 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds printk(KERN_INFO "hisax_st5481: ST5481 USB ISDN driver $Revision: 2.4.2.3 $\n"); 1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = st5481_d_init(); 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out; 2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = usb_register(&st5481_usb_driver); 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (retval < 0) 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_d_exit; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 208475be4d85a274d0961593db41cf85689db1d583cJoe Perchesout_d_exit: 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_d_exit(); 210475be4d85a274d0961593db41cf85689db1d583cJoe Perchesout: 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void __exit st5481_usb_exit(void) 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds usb_deregister(&st5481_usb_driver); 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds st5481_d_exit(); 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(st5481_usb_init); 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_exit(st5481_usb_exit); 222