/* Device-specific structure */
typedef struct {
    struct usb_device *usbdev;       /* Device representation */
    struct usb_interface *interface; /* Interface representation*/
    struct urb *ctrl_urb;            /* Control URB for
                                        register access */
    struct usb_ctrlrequest ctrl_req; /* Control request
                                        as per the spec */
    unsigned char *bulk_in_buf;      /* Receive data buffer */
    size_t bulk_in_len;              /* Receive buffer size */
    __u8 bulk_in_addr;               /* IN endpoint address */
    __u8 bulk_out_addr;              /* OUT endpoint address */
    /* ... */                        /* Locks, waitqueues,
                                        statistics.. */
} tele_device_t;

#define TELE_MINOR_BASE 0xAB /* Assigned by the Linux-USB

                                subsystem maintainer */

/* Conventional char driver entry points.
   See Chapter 5, "Character Drivers." */
static struct file_operations tele_fops =
    {
        .owner = THIS_MODULE,    /* Owner */
        .read = tele_read,       /* Read method */
        .write = tele_write,     /* Write method */
        .ioctl = tele_ioctl,     /* Ioctl method */
        .open = tele_open,       /* Open method */
        .release = tele_release, /* Close method */
    };

static struct usb_class_driver tele_class = {
    .name = "tele",
    .fops = &tele_fops,            /* Connect with /dev/tele */
    .minor_base = TELE_MINOR_BASE, /* Minor number start */
};

/* The probe() method is invoked by khubd after device
   enumeration. The first argument interface, contains information
   gleaned during the enumeration process. id is the entry in the
   driverís usb_device_id table that matches the values read from
   the telemetry card. tele_probe() is based on skel_probe()
   defined in drivers/usb/usb-skeleton.c */
static int
tele_probe(struct usb_interface *interface,
           const struct usb_device_id *id)
{
    struct usb_host_interface *iface_desc;
    struct usb_endpoint_descriptor *endpoint;
    tele_device_t *tele_device;
    int retval = -ENOMEM;

    /* Allocate the device-specific structure */
    tele_device = kzalloc(sizeof(tele_device_t), GFP_KERNEL);

    /* Fill the usb_device and usb_interface */
    tele_device->usbdev =
        usb_get_dev(interface_to_usbdev(interface));
    tele_device->interface = interface;

    /* Set up endpoint information from the data gleaned
       during device enumeration */
    iface_desc = interface->cur_altsetting;
    for (int i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
        endpoint = &iface_desc->endpoint[i].desc;
        if (!tele_device->bulk_in_addr &&
            usb_endpoint_is_bulk_in(endpoint)) {
            /* Bulk IN endpoint */
            tele_device->bulk_in_len =
                le16_to_cpu(endpoint->wMaxPacketSize);
            tele_device->bulk_in_addr = endpoint->bEndpointAddress;
            tele_device->bulk_in_buf =
                kmalloc(tele_device->bulk_in_len, GFP_KERNEL);
        }
        if (!tele_device->bulk_out_addr &&
            usb_endpoint_is_bulk_out(endpoint)) {
            /* Bulk OUT endpoint */
            tele_device->bulk_out_addr = endpoint->bEndpointAddress;
        }
        
    }

    if (!(tele_device->bulk_in_addr && tele_device->bulk_out_addr)) {
        return retval;
    }

    /* Attach the device-specific structure to this interface.
       We will retrieve it from tele_open() */
    usb_set_intfdata(interface, tele_device);

    /* Register the device */
    retval = usb_register_dev(interface, &tele_class);
    if (retval) {
        usb_set_intfdata(interface, NULL);
        return retval;
    }

    printk("Telemetry device now attached to /dev/tele\n");
    return 0;
}

/* Disconnect method. Called when the device is unplugged or when the module is
   unloaded */
static void
tele_disconnect(struct usb_interface *interface)
{
    tele_device_t *tele_device;

    /* ... */

    /* Reverse of usb_set_intfdata() invoked from tele_probe() */
    tele_device = usb_get_intfdata(interface);

    /* Zero out interface data */
    usb_set_intfdata(interface, NULL);

    /* Release /dev/tele */
    usb_deregister_dev(interface, &tele_class);

    /* NULL the interface. In the real world, protect this
       operation using locks */
    tele_device->interface = NULL;

    /* ... */
}


syntax highlighted by Code2HTML, v. 0.9.1