1/* 2 * Driver for ST5481 USB ISDN modem 3 * 4 * Author Frode Isaksen 5 * Copyright 2001 by Frode Isaksen <fisaksen@bewan.com> 6 * 2001 by Kai Germaschewski <kai.germaschewski@gmx.de> 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 */ 12 13/* 14 * TODO: 15 * 16 * b layer1 delay? 17 * hdlc as module 18 * hotplug / unregister issues 19 * mod_inc/dec_use_count 20 * unify parts of d/b channel usb handling 21 * file header 22 * avoid copy to isoc buffer? 23 * improve usb delay? 24 * merge l1 state machines? 25 * clean up debug 26 */ 27 28#include <linux/config.h> 29#include <linux/version.h> 30#include <linux/module.h> 31#include <linux/init.h> 32#include <linux/usb.h> 33#include <linux/slab.h> 34#include "st5481.h" 35 36MODULE_DESCRIPTION("ISDN4Linux: driver for ST5481 USB ISDN adapter"); 37MODULE_AUTHOR("Frode Isaksen"); 38MODULE_LICENSE("GPL"); 39 40static int protocol = 2; /* EURO-ISDN Default */ 41MODULE_PARM(protocol, "i"); 42 43static int number_of_leds = 2; /* 2 LEDs on the adpater default */ 44MODULE_PARM(number_of_leds, "i"); 45 46#ifdef CONFIG_HISAX_DEBUG 47static int debug = 0x1; 48MODULE_PARM(debug, "i"); 49int st5481_debug; 50#endif 51 52static LIST_HEAD(adapter_list); 53 54/* ====================================================================== 55 * registration/deregistration with the USB layer 56 */ 57 58/* 59 * This function will be called when the adapter is plugged 60 * into the USB bus. 61 */ 62static void * __devinit probe_st5481(struct usb_device *dev, 63 unsigned int ifnum, 64 const struct usb_device_id *id) 65{ 66 struct st5481_adapter *adapter; 67 struct hisax_b_if *b_if[2]; 68 int retval, i; 69 70 printk(KERN_INFO "st541: found adapter VendorId %04x, ProductId %04x, LEDs %d\n", 71 dev->descriptor.idVendor, dev->descriptor.idProduct, 72 number_of_leds); 73 74 adapter = kmalloc(sizeof(struct st5481_adapter), GFP_KERNEL); 75 if (!adapter) 76 return NULL; 77 78 memset(adapter, 0, sizeof(struct st5481_adapter)); 79 80 adapter->number_of_leds = number_of_leds; 81 adapter->usb_dev = dev; 82 83 SET_MODULE_OWNER(&adapter->hisax_d_if); 84 adapter->hisax_d_if.ifc.priv = adapter; 85 adapter->hisax_d_if.ifc.l2l1 = st5481_d_l2l1; 86 87 for (i = 0; i < 2; i++) { 88 adapter->bcs[i].adapter = adapter; 89 adapter->bcs[i].channel = i; 90 adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i]; 91 adapter->bcs[i].b_if.ifc.l2l1 = st5481_b_l2l1; 92 } 93 list_add(&adapter->list, &adapter_list); 94 95 retval = st5481_setup_usb(adapter); 96 if (retval < 0) 97 goto err; 98 99 retval = st5481_setup_d(adapter); 100 if (retval < 0) 101 goto err_usb; 102 103 retval = st5481_setup_b(&adapter->bcs[0]); 104 if (retval < 0) 105 goto err_d; 106 107 retval = st5481_setup_b(&adapter->bcs[1]); 108 if (retval < 0) 109 goto err_b; 110 111 for (i = 0; i < 2; i++) 112 b_if[i] = &adapter->bcs[i].b_if; 113 114 hisax_register(&adapter->hisax_d_if, b_if, "st5481_usb", protocol); 115 st5481_start(adapter); 116 117 return adapter; 118 119 err_b: 120 st5481_release_b(&adapter->bcs[0]); 121 err_d: 122 st5481_release_d(adapter); 123 err_usb: 124 st5481_release_usb(adapter); 125 err: 126 return NULL; 127} 128 129/* 130 * This function will be called when the adapter is removed 131 * from the USB bus. 132 */ 133static void __devexit disconnect_st5481(struct usb_device *dev, void *arg) 134{ 135 struct st5481_adapter *adapter = arg; 136 137 DBG(1,""); 138 139 list_del(&adapter->list); 140 141 st5481_stop(adapter); 142 st5481_release_b(&adapter->bcs[1]); 143 st5481_release_b(&adapter->bcs[0]); 144 st5481_release_d(adapter); 145 // we would actually better wait for completion of outstanding urbs 146 mdelay(2); 147 st5481_release_usb(adapter); 148 149 hisax_unregister(&adapter->hisax_d_if); 150 151 kfree(adapter); 152} 153 154/* 155 * The last 4 bits in the Product Id is set with 4 pins on the chip. 156 */ 157static struct usb_device_id st5481_ids[] = { 158 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x0) }, 159 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x1) }, 160 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x2) }, 161 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x3) }, 162 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x4) }, 163 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x5) }, 164 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x6) }, 165 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x7) }, 166 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x8) }, 167 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0x9) }, 168 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xA) }, 169 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xB) }, 170 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xC) }, 171 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xD) }, 172 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xE) }, 173 { USB_DEVICE(ST_VENDOR_ID, ST5481_PRODUCT_ID+0xF) }, 174 { } 175}; 176MODULE_DEVICE_TABLE (usb, st5481_ids); 177 178static struct usb_driver st5481_usb_driver = { 179 name: "st5481_usb", 180 probe: probe_st5481, 181 disconnect: __devexit_p(disconnect_st5481), 182 id_table: st5481_ids, 183}; 184 185static int __init st5481_usb_init(void) 186{ 187 int retval; 188 189#ifdef CONFIG_HISAX_DEBUG 190 st5481_debug = debug; 191#endif 192 193 printk(KERN_INFO "hiax_st5481: ST5481 USB ISDN driver v0.1.0\n"); 194 195 retval = st5481_d_init(); 196 if (retval < 0) 197 goto out; 198 199 retval = usb_register(&st5481_usb_driver); 200 if (retval < 0) 201 goto out_d_exit; 202 203 return 0; 204 205 out_d_exit: 206 st5481_d_exit(); 207 out: 208 return retval; 209} 210 211static void __exit st5481_usb_exit(void) 212{ 213 usb_deregister(&st5481_usb_driver); 214} 215 216module_init(st5481_usb_init); 217module_exit(st5481_usb_exit); 218