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