diff options
author | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-29 01:11:23 -0400 |
---|---|---|
committer | Dmitry Torokhov <dtor_core@ameritech.net> | 2006-04-29 01:11:23 -0400 |
commit | 7b7e394185014e0f3bd8989cac937003f20ef9ce (patch) | |
tree | 3beda5f979bba0aa9822534e239cf1b45f3be69c /drivers/isdn/gigaset/usb-gigaset.c | |
parent | ddc5d3414593e4d7ad7fbd33e7f7517fcc234544 (diff) | |
parent | 693f7d362055261882659475d2ef022e32edbff1 (diff) |
Merge rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/isdn/gigaset/usb-gigaset.c')
-rw-r--r-- | drivers/isdn/gigaset/usb-gigaset.c | 455 |
1 files changed, 204 insertions, 251 deletions
diff --git a/drivers/isdn/gigaset/usb-gigaset.c b/drivers/isdn/gigaset/usb-gigaset.c index 323fc7349de..bfb73fd5077 100644 --- a/drivers/isdn/gigaset/usb-gigaset.c +++ b/drivers/isdn/gigaset/usb-gigaset.c @@ -1,7 +1,7 @@ /* * USB driver for Gigaset 307x directly or using M105 Data. * - * Copyright (c) 2001 by Stefan Eilers <Eilers.Stefan@epost.de> + * Copyright (c) 2001 by Stefan Eilers * and Hansjoerg Lipp <hjlipp@web.de>. * * This driver was derived from the USB skeleton driver by @@ -13,10 +13,6 @@ * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * ===================================================================== - * ToDo: ... - * ===================================================================== - * Version: $Id: usb-gigaset.c,v 1.85.4.18 2006/02/04 18:28:16 hjlipp Exp $ - * ===================================================================== */ #include "gigaset.h" @@ -29,7 +25,7 @@ #include <linux/moduleparam.h> /* Version Information */ -#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers <Eilers.Stefan@epost.de>" +#define DRIVER_AUTHOR "Hansjoerg Lipp <hjlipp@web.de>, Stefan Eilers" #define DRIVER_DESC "USB Driver for Gigaset 307x using M105" /* Module parameters */ @@ -62,10 +58,6 @@ static struct usb_device_id gigaset_table [] = { MODULE_DEVICE_TABLE(usb, gigaset_table); -/* Get a minor range for your devices from the usb maintainer */ -#define USB_SKEL_MINOR_BASE 200 - - /* * Control requests (empty fields: 00) * @@ -114,7 +106,7 @@ MODULE_DEVICE_TABLE(usb, gigaset_table); */ static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id); + const struct usb_device_id *id); static void gigaset_disconnect(struct usb_interface *interface); static struct gigaset_driver *driver = NULL; @@ -122,29 +114,29 @@ static struct cardstate *cardstate = NULL; /* usb specific object needed to register this driver with the usb subsystem */ static struct usb_driver gigaset_usb_driver = { - .name = GIGASET_MODULENAME, - .probe = gigaset_probe, - .disconnect = gigaset_disconnect, - .id_table = gigaset_table, + .name = GIGASET_MODULENAME, + .probe = gigaset_probe, + .disconnect = gigaset_disconnect, + .id_table = gigaset_table, }; struct usb_cardstate { - struct usb_device *udev; /* save off the usb device pointer */ - struct usb_interface *interface; /* the interface for this device */ - atomic_t busy; /* bulk output in progress */ - - /* Output buffer for commands (M105: and data)*/ - unsigned char *bulk_out_buffer; /* the buffer to send data */ - int bulk_out_size; /* the size of the send buffer */ - __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ - struct urb *bulk_out_urb; /* the urb used to transmit data */ - - /* Input buffer for command responses (M105: and data)*/ - int rcvbuf_size; /* the size of the receive buffer */ - struct urb *read_urb; /* the urb used to receive data */ - __u8 int_in_endpointAddr; /* the address of the bulk in endpoint */ - - char bchars[6]; /* req. 0x19 */ + struct usb_device *udev; /* usb device pointer */ + struct usb_interface *interface; /* interface for this device */ + atomic_t busy; /* bulk output in progress */ + + /* Output buffer */ + unsigned char *bulk_out_buffer; + int bulk_out_size; + __u8 bulk_out_endpointAddr; + struct urb *bulk_out_urb; + + /* Input buffer */ + int rcvbuf_size; + struct urb *read_urb; + __u8 int_in_endpointAddr; + + char bchars[6]; /* for request 0x19 */ }; struct usb_bc_state {}; @@ -157,19 +149,20 @@ static inline unsigned tiocm_to_gigaset(unsigned state) #ifdef CONFIG_GIGASET_UNDOCREQ /* WARNING: EXPERIMENTAL! */ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { + struct usb_device *udev = cs->hw.usb->udev; unsigned mask, val; int r; mask = tiocm_to_gigaset(old_state ^ new_state); val = tiocm_to_gigaset(new_state); - dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 7, 0x41, - (val & 0xff) | ((mask & 0xff) << 8), 0, - NULL, 0, 2000 /*timeout??*/); // don't use this in an interrupt/BH + gig_dbg(DEBUG_USBREQ, "set flags 0x%02x with mask 0x%02x", val, mask); + // don't use this in an interrupt/BH + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 7, 0x41, + (val & 0xff) | ((mask & 0xff) << 8), 0, + NULL, 0, 2000 /* timeout? */); if (r < 0) return r; //.. @@ -178,30 +171,29 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, static int set_value(struct cardstate *cs, u8 req, u16 val) { + struct usb_device *udev = cs->hw.usb->udev; int r, r2; - dbg(DEBUG_USBREQ, "request %02x (%04x)", (unsigned)req, (unsigned)val); - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x12, 0x41, - 0xf /*?*/, 0, - NULL, 0, 2000 /*?*/); /* no idea, what this does */ + gig_dbg(DEBUG_USBREQ, "request %02x (%04x)", + (unsigned)req, (unsigned)val); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x12, 0x41, + 0xf /*?*/, 0, NULL, 0, 2000 /*?*/); + /* no idea what this does */ if (r < 0) { - err("error %d on request 0x12", -r); + dev_err(&udev->dev, "error %d on request 0x12\n", -r); return r; } - r = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), req, 0x41, - val, 0, - NULL, 0, 2000 /*?*/); + r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), req, 0x41, + val, 0, NULL, 0, 2000 /*?*/); if (r < 0) - err("error %d on request 0x%02x", -r, (unsigned)req); + dev_err(&udev->dev, "error %d on request 0x%02x\n", + -r, (unsigned)req); - r2 = usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); + r2 = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, cs->hw.usb->bchars, 6, 2000 /*?*/); if (r2 < 0) - err("error %d on request 0x19", -r2); + dev_err(&udev->dev, "error %d on request 0x19\n", -r2); return r < 0 ? r : (r2 < 0 ? r2 : 0); } @@ -229,8 +221,8 @@ static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag) case B115200: rate = 115200; break; default: rate = 9600; - err("unsupported baudrate request 0x%x," - " using default of B9600", cflag); + dev_err(cs->dev, "unsupported baudrate request 0x%x," + " using default of B9600\n", cflag); } val = 0x383fff / rate + 1; @@ -259,7 +251,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) case CS8: val |= 8 << 8; break; default: - err("CSIZE was not CS5-CS8, using default of 8"); + dev_err(cs->dev, "CSIZE was not CS5-CS8, using default of 8\n"); val |= 8 << 8; break; } @@ -277,7 +269,7 @@ static int gigaset_set_line_ctrl(struct cardstate *cs, unsigned cflag) #else static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, - unsigned new_state) + unsigned new_state) { return -EINVAL; } @@ -309,15 +301,12 @@ static int gigaset_close_bchannel(struct bc_state *bcs) return 0; } -//void send_ack_to_LL(void *data); static int write_modem(struct cardstate *cs); static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb); -/* Handling of send queue. If there is already a skb opened, put data to - * the transfer buffer by calling "write_modem". Otherwise take a new skb out of the queue. - * This function will be called by the ISR via "transmit_chars" (USB: B-Channel Bulk callback handler - * via immediate task queue) or by writebuf_from_LL if the LL wants to transmit data. +/* Write tasklet handler: Continue sending current skb, or send command, or + * start sending an skb from the send queue. */ static void gigaset_modem_fill(unsigned long data) { @@ -327,10 +316,10 @@ static void gigaset_modem_fill(unsigned long data) unsigned long flags; int again; - dbg(DEBUG_OUTPUT, "modem_fill"); + gig_dbg(DEBUG_OUTPUT, "modem_fill"); if (atomic_read(&cs->hw.usb->busy)) { - dbg(DEBUG_OUTPUT, "modem_fill: busy"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: busy"); return; } @@ -341,26 +330,27 @@ static void gigaset_modem_fill(unsigned long data) cb = cs->cmdbuf; spin_unlock_irqrestore(&cs->cmdlock, flags); if (cb) { /* commands to send? */ - dbg(DEBUG_OUTPUT, "modem_fill: cb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: cb"); if (send_cb(cs, cb) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: send_cb failed"); - again = 1; /* no callback will be called! */ + gig_dbg(DEBUG_OUTPUT, + "modem_fill: send_cb failed"); + again = 1; /* no callback will be + called! */ } } else { /* skbs to send? */ bcs->tx_skb = skb_dequeue(&bcs->squeue); if (bcs->tx_skb) - dbg(DEBUG_INTR, - "Dequeued skb (Adr: %lx)!", - (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, + "Dequeued skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); } } if (bcs->tx_skb) { - dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); + gig_dbg(DEBUG_OUTPUT, "modem_fill: tx_skb"); if (write_modem(cs) < 0) { - dbg(DEBUG_OUTPUT, - "modem_fill: write_modem failed"); + gig_dbg(DEBUG_OUTPUT, + "modem_fill: write_modem failed"); // FIXME should we tell the LL? again = 1; /* no callback will be called! */ } @@ -371,88 +361,85 @@ static void gigaset_modem_fill(unsigned long data) /** * gigaset_read_int_callback * - * It is called if the data was received from the device. This is almost similiar to - * the interrupt service routine in the serial device. + * It is called if the data was received from the device. */ static void gigaset_read_int_callback(struct urb *urb, struct pt_regs *regs) { + struct inbuf_t *inbuf = urb->context; + struct cardstate *cs = inbuf->cs; int resubmit = 0; int r; - struct cardstate *cs; unsigned numbytes; unsigned char *src; - //unsigned long flags; - struct inbuf_t *inbuf; - - IFNULLRET(urb); - inbuf = (struct inbuf_t *) urb->context; - IFNULLRET(inbuf); - //spin_lock_irqsave(&inbuf->lock, flags); - cs = inbuf->cs; - IFNULLGOTO(cs, exit); - IFNULLGOTO(cardstate, exit); - - if (!atomic_read(&cs->connected)) { - err("%s: disconnected", __func__); - goto exit; - } + unsigned long flags; if (!urb->status) { + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } + numbytes = urb->actual_length; if (numbytes) { src = inbuf->rcvbuf; if (unlikely(*src)) - warn("%s: There was no leading 0, but 0x%02x!", - __func__, (unsigned) *src); + dev_warn(cs->dev, + "%s: There was no leading 0, but 0x%02x!\n", + __func__, (unsigned) *src); ++src; /* skip leading 0x00 */ --numbytes; if (gigaset_fill_inbuf(inbuf, src, numbytes)) { - dbg(DEBUG_INTR, "%s-->BH", __func__); + gig_dbg(DEBUG_INTR, "%s-->BH", __func__); gigaset_schedule_event(inbuf->cs); } } else - dbg(DEBUG_INTR, "Received zero block length"); + gig_dbg(DEBUG_INTR, "Received zero block length"); resubmit = 1; } else { /* The urb might have been killed. */ - dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", - __func__, urb->status); - if (urb->status != -ENOENT) /* not killed */ + gig_dbg(DEBUG_ANY, "%s - nonzero read bulk status received: %d", + __func__, urb->status); + if (urb->status != -ENOENT) { /* not killed */ + if (!cs->connected) { + err("%s: disconnected", __func__); /* should never happen */ + return; + } resubmit = 1; + } } -exit: - //spin_unlock_irqrestore(&inbuf->lock, flags); + if (resubmit) { - r = usb_submit_urb(urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + r = cs->connected ? usb_submit_urb(urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); if (r) - err("error %d when resubmitting urb.", -r); + dev_err(cs->dev, "error %d when resubmitting urb.\n", + -r); } } -/* This callback routine is called when data was transmitted to a B-Channel. - * Therefore it has to check if there is still data to transmit. This - * happens by calling modem_fill via task queue. - * - */ +/* This callback routine is called when data was transmitted to the device. */ static void gigaset_write_bulk_callback(struct urb *urb, struct pt_regs *regs) { - struct cardstate *cs = (struct cardstate *) urb->context; + struct cardstate *cs = urb->context; + unsigned long flags; - IFNULLRET(cs); -#ifdef CONFIG_GIGASET_DEBUG - if (!atomic_read(&cs->connected)) { - err("%s:not connected", __func__); - return; - } -#endif if (urb->status) - err("bulk transfer failed (status %d)", -urb->status); /* That's all we can do. Communication problems - are handeled by timeouts or network protocols */ + dev_err(cs->dev, "bulk transfer failed (status %d)\n", + -urb->status); + /* That's all we can do. Communication problems + are handled by timeouts or network protocols. */ - atomic_set(&cs->hw.usb->busy, 0); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (!cs->connected) { + err("%s: not connected", __func__); + } else { + atomic_set(&cs->hw.usb->busy, 0); + tasklet_schedule(&cs->write_tasklet); + } + spin_unlock_irqrestore(&cs->lock, flags); } static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) @@ -469,8 +456,8 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) spin_lock_irqsave(&cs->cmdlock, flags); cs->cmdbytes -= cs->curlen; - dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", - cs->curlen, cs->cmdbytes); + gig_dbg(DEBUG_OUTPUT, "send_cb: sent %u bytes, %u left", + cs->curlen, cs->cmdbytes); cs->cmdbuf = cb = cb->next; if (cb) { cb->prev = NULL; @@ -487,52 +474,51 @@ static int send_cb(struct cardstate *cs, struct cmdbuf_t *cb) } if (cb) { count = min(cb->len, ucs->bulk_out_size); + gig_dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - cb->buf + cb->offset, count, - gigaset_write_bulk_callback, cs); + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + cb->buf + cb->offset, count, + gigaset_write_bulk_callback, cs); cb->offset += count; cb->len -= count; atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "send_cb: send %d bytes", count); - status = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + spin_lock_irqsave(&cs->lock, flags); + status = cs->connected ? usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC) : -ENODEV; + spin_unlock_irqrestore(&cs->lock, flags); + if (status) { atomic_set(&ucs->busy, 0); - err("could not submit urb (error %d).", + err("could not submit urb (error %d)\n", -status); - cb->len = 0; /* skip urb => remove cb+wakeup in next loop cycle */ + cb->len = 0; /* skip urb => remove cb+wakeup + in next loop cycle */ } } - } while (cb && status); /* bei Fehler naechster Befehl //FIXME: ist das OK? */ + } while (cb && status); /* next command on error */ return status; } -/* Write string into transbuf and send it to modem. - */ +/* Send command to device. */ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, - int len, struct tasklet_struct *wake_tasklet) + int len, struct tasklet_struct *wake_tasklet) { struct cmdbuf_t *cb; unsigned long flags; gigaset_dbg_buffer(atomic_read(&cs->mstate) != MS_LOCKED ? - DEBUG_TRANSCMD : DEBUG_LOCKCMD, - "CMD Transmit", len, buf, 0); - - if (!atomic_read(&cs->connected)) { - err("%s: not connected", __func__); - return -ENODEV; - } + DEBUG_TRANSCMD : DEBUG_LOCKCMD, + "CMD Transmit", len, buf); if (len <= 0) return 0; if (!(cb = kmalloc(sizeof(struct cmdbuf_t) + len, GFP_ATOMIC))) { - err("%s: out of memory", __func__); + dev_err(cs->dev, "%s: out of memory\n", __func__); return -ENOMEM; } @@ -554,7 +540,10 @@ static int gigaset_write_cmd(struct cardstate *cs, const unsigned char *buf, cs->lastcmdbuf = cb; spin_unlock_irqrestore(&cs->cmdlock, flags); - tasklet_schedule(&cs->write_tasklet); + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) + tasklet_schedule(&cs->write_tasklet); + spin_unlock_irqrestore(&cs->lock, flags); return len; } @@ -578,11 +567,12 @@ static int gigaset_chars_in_buffer(struct cardstate *cs) static int gigaset_brkchars(struct cardstate *cs, const unsigned char buf[6]) { #ifdef CONFIG_GIGASET_UNDOCREQ - gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf, 0); + struct usb_device *udev = cs->hw.usb->udev; + + gigaset_dbg_buffer(DEBUG_USBREQ, "brkchars", 6, buf); memcpy(cs->hw.usb->bchars, buf, 6); - return usb_control_msg(cs->hw.usb->udev, - usb_sndctrlpipe(cs->hw.usb->udev, 0), 0x19, 0x41, - 0, 0, &buf, 6, 2000); + return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x19, 0x41, + 0, 0, &buf, 6, 2000); #else return -EINVAL; #endif @@ -604,7 +594,6 @@ static int gigaset_initbcshw(struct bc_state *bcs) if (!bcs->hw.usb) return 0; - //bcs->hw.usb->trans_flg = READY_TO_TRNSMIT; /* B-Channel ready to transmit */ return 1; } @@ -614,7 +603,6 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { - //FIXME tasklet_kill(&cs->write_tasklet); kfree(cs->hw.usb); } @@ -639,33 +627,21 @@ static int gigaset_initcshw(struct cardstate *cs) //ucs->urb_cmd_out = NULL; ucs->read_urb = NULL; tasklet_init(&cs->write_tasklet, - &gigaset_modem_fill, (unsigned long) cs); + &gigaset_modem_fill, (unsigned long) cs); return 1; } -/* Writes the data of the current open skb into the modem. - * We have to protect against multiple calls until the - * callback handler () is called , due to the fact that we - * are just allowed to send data once to an endpoint. Therefore - * we using "trans_flg" to synchonize ... - */ +/* Send data from current skb to the device. */ static int write_modem(struct cardstate *cs) { - int ret; + int ret = 0; int count; struct bc_state *bcs = &cs->bcs[0]; /* only one channel */ struct usb_cardstate *ucs = cs->hw.usb; - //unsigned long flags; - - IFNULLRETVAL(bcs->tx_skb, -EINVAL); - - dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); + unsigned long flags; - ret = -ENODEV; - IFNULLGOTO(ucs->bulk_out_buffer, error); - IFNULLGOTO(ucs->bulk_out_urb, error); - ret = 0; + gig_dbg(DEBUG_WRITE, "len: %d...", bcs->tx_skb->len); if (!bcs->tx_skb->len) { dev_kfree_skb_any(bcs->tx_skb); @@ -679,40 +655,42 @@ static int write_modem(struct cardstate *cs) count = min(bcs->tx_skb->len, (unsigned) ucs->bulk_out_size); memcpy(ucs->bulk_out_buffer, bcs->tx_skb->data, count); skb_pull(bcs->tx_skb, count); - - usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, - usb_sndbulkpipe(ucs->udev, - ucs->bulk_out_endpointAddr & 0x0f), - ucs->bulk_out_buffer, count, - gigaset_write_bulk_callback, cs); atomic_set(&ucs->busy, 1); - dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + gig_dbg(DEBUG_OUTPUT, "write_modem: send %d bytes", count); + + spin_lock_irqsave(&cs->lock, flags); + if (cs->connected) { + usb_fill_bulk_urb(ucs->bulk_out_urb, ucs->udev, + usb_sndbulkpipe(ucs->udev, + ucs->bulk_out_endpointAddr & 0x0f), + ucs->bulk_out_buffer, count, + gigaset_write_bulk_callback, cs); + ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); + } else { + ret = -ENODEV; + } + spin_unlock_irqrestore(&cs->lock, flags); - ret = usb_submit_urb(ucs->bulk_out_urb, SLAB_ATOMIC); if (ret) { - err("could not submit urb (error %d).", -ret); + err("could not submit urb (error %d)\n", -ret); atomic_set(&ucs->busy, 0); } + if (!bcs->tx_skb->len) { /* skb sent completely */ gigaset_skb_sent(bcs, bcs->tx_skb); //FIXME also, when ret<0? - dbg(DEBUG_INTR, - "kfree skb (Adr: %lx)!", (unsigned long) bcs->tx_skb); + gig_dbg(DEBUG_INTR, "kfree skb (Adr: %lx)!", + (unsigned long) bcs->tx_skb); dev_kfree_skb_any(bcs->tx_skb); bcs->tx_skb = NULL; } return ret; -error: - dev_kfree_skb_any(bcs->tx_skb); - bcs->tx_skb = NULL; - return ret; - } static int gigaset_probe(struct usb_interface *interface, - const struct usb_device_id *id) + const struct usb_device_id *id) { int retval; struct usb_device *udev = interface_to_usbdev(interface); @@ -720,16 +698,14 @@ static int gigaset_probe(struct usb_interface *interface, struct usb_host_interface *hostif; struct cardstate *cs = NULL; struct usb_cardstate *ucs = NULL; - //struct usb_interface_descriptor *iface_desc; struct usb_endpoint_descriptor *endpoint; - //isdn_ctrl command; int buffer_size; int alt; - //unsigned long flags; - info("%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", - __func__, le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct)); + gig_dbg(DEBUG_ANY, + "%s: Check if device matches .. (Vendor: 0x%x, Product: 0x%x)", + __func__, le16_to_cpu(udev->descriptor.idVendor), + le16_to_cpu(udev->descriptor.idProduct)); retval = -ENODEV; //FIXME @@ -744,7 +720,7 @@ static int gigaset_probe(struct usb_interface *interface, ifnum = hostif->desc.bInterfaceNumber; // FIXME ? if (alt != 0 || ifnum != 0) { - warn("ifnum %d, alt %d", ifnum, alt); + dev_warn(&udev->dev, "ifnum %d, alt %d\n", ifnum, alt); return -ENODEV; } @@ -752,42 +728,29 @@ static int gigaset_probe(struct usb_interface *interface, * */ if (hostif->desc.bInterfaceClass != 255) { - info("%s: Device matched, but iface_desc[%d]->bInterfaceClass==%d !", - __func__, ifnum, hostif->desc.bInterfaceClass); + dev_info(&udev->dev, + "%s: Device matched but iface_desc[%d]->bInterfaceClass==%d!\n", + __func__, ifnum, hostif->desc.bInterfaceClass); return -ENODEV; } - info("%s: Device matched ... !", __func__); + dev_info(&udev->dev, "%s: Device matched ... !\n", __func__); cs = gigaset_getunassignedcs(driver); if (!cs) { - warn("No free cardstate!"); + dev_warn(&udev->dev, "no free cardstate\n"); return -ENODEV; } ucs = cs->hw.usb; -#if 0 - if (usb_set_configuration(udev, udev->config[0].desc.bConfigurationValue) < 0) { - warn("set_configuration failed"); - goto error; - } - - - if (usb_set_interface(udev, ifnum/*==0*/, alt/*==0*/) < 0) { - warn("usb_set_interface failed, device %d interface %d altsetting %d", - udev->devnum, ifnum, alt); - goto error; - } -#endif + /* save off device structure ptrs for later use */ + usb_get_dev(udev); + ucs->udev = udev; + ucs->interface = interface; + cs->dev = &interface->dev; - /* set up the endpoint information */ - /* check out the endpoints */ - /* We will get 2 endpoints: One for sending commands to the device (bulk out) and one to - * poll messages from the device(int in). - * Therefore we will have an almost similiar situation as with our serial port handler. - * If an connection will be established, we will have to create data in/out pipes - * dynamically... - */ + /* save address of controller structure */ + usb_set_intfdata(interface, cs); // dev_set_drvdata(&interface->dev, cs); endpoint = &hostif->endpoint[0].desc; @@ -796,14 +759,14 @@ static int gigaset_probe(struct usb_interface *interface, ucs->bulk_out_endpointAddr = endpoint->bEndpointAddress; ucs->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!ucs->bulk_out_buffer) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_buffer\n"); retval = -ENOMEM; goto error; } ucs->bulk_out_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->bulk_out_urb) { - err("Couldn't allocate bulk_out_buffer"); + dev_err(cs->dev, "Couldn't allocate bulk_out_urb\n"); retval = -ENOMEM; goto error; } @@ -811,12 +774,10 @@ static int gigaset_probe(struct usb_interface *interface, endpoint = &hostif->endpoint[1].desc; atomic_set(&ucs->busy, 0); - ucs->udev = udev; - ucs->interface = interface; ucs->read_urb = usb_alloc_urb(0, SLAB_KERNEL); if (!ucs->read_urb) { - err("No free urbs available"); + dev_err(cs->dev, "No free urbs available\n"); retval = -ENOMEM; goto error; } @@ -825,38 +786,33 @@ static int gigaset_probe(struct usb_interface *interface, ucs->int_in_endpointAddr = endpoint->bEndpointAddress; cs->inbuf[0].rcvbuf = kmalloc(buffer_size, GFP_KERNEL); if (!cs->inbuf[0].rcvbuf) { - err("Couldn't allocate rcvbuf"); + dev_err(cs->dev, "Couldn't allocate rcvbuf\n"); retval = -ENOMEM; goto error; } /* Fill the interrupt urb and send it to the core */ usb_fill_int_urb(ucs->read_urb, udev, - usb_rcvintpipe(udev, - endpoint->bEndpointAddress & 0x0f), - cs->inbuf[0].rcvbuf, buffer_size, - gigaset_read_int_callback, - cs->inbuf + 0, endpoint->bInterval); + usb_rcvintpipe(udev, + endpoint->bEndpointAddress & 0x0f), + cs->inbuf[0].rcvbuf, buffer_size, + gigaset_read_int_callback, + cs->inbuf + 0, endpoint->bInterval); retval = usb_submit_urb(ucs->read_urb, SLAB_KERNEL); if (retval) { - err("Could not submit URB!"); + dev_err(cs->dev, "Could not submit URB (error %d)\n", -retval); goto error; } /* tell common part that the device is ready */ if (startmode == SM_LOCKED) atomic_set(&cs->mstate, MS_LOCKED); + if (!gigaset_start(cs)) { tasklet_kill(&cs->write_tasklet); retval = -ENODEV; //FIXME goto error; } - - /* save address of controller structure */ - usb_set_intfdata(interface, cs); - - /* set up device sysfs */ - gigaset_init_dev_sysfs(interface); return 0; error: @@ -868,48 +824,45 @@ error: kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); + usb_set_intfdata(interface, NULL); ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->udev = NULL; + ucs->interface = NULL; gigaset_unassign(cs); return retval; } -/** - * skel_disconnect - */ static void gigaset_disconnect(struct usb_interface *interface) { struct cardstate *cs; struct usb_cardstate *ucs; cs = usb_get_intfdata(interface); - - /* clear device sysfs */ - gigaset_free_dev_sysfs(interface); - - usb_set_intfdata(interface, NULL); ucs = cs->hw.usb; usb_kill_urb(ucs->read_urb); - //info("GigaSet USB device #%d will be disconnected", minor); gigaset_stop(cs); + usb_set_intfdata(interface, NULL); tasklet_kill(&cs->write_tasklet); - usb_kill_urb(ucs->bulk_out_urb); /* FIXME: nur, wenn noetig */ - //usb_kill_urb(ucs->urb_cmd_out); /* FIXME: nur, wenn noetig */ + usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ kfree(ucs->bulk_out_buffer); if (ucs->bulk_out_urb != NULL) usb_free_urb(ucs->bulk_out_urb); - //if(ucs->urb_cmd_out != NULL) - // usb_free_urb(ucs->urb_cmd_out); kfree(cs->inbuf[0].rcvbuf); if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb); - ucs->read_urb = ucs->bulk_out_urb/*=ucs->urb_cmd_out*/=NULL; + ucs->read_urb = ucs->bulk_out_urb = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; + usb_put_dev(ucs->udev); + ucs->interface = NULL; + ucs->udev = NULL; + cs->dev = NULL; gigaset_unassign(cs); } @@ -942,9 +895,9 @@ static int __init usb_gigaset_init(void) /* allocate memory for our driver state and intialize it */ if ((driver = gigaset_initdriver(GIGASET_MINOR, GIGASET_MINORS, - GIGASET_MODULENAME, GIGASET_DEVNAME, - GIGASET_DEVFSNAME, &ops, - THIS_MODULE)) == NULL) + GIGASET_MODULENAME, GIGASET_DEVNAME, + GIGASET_DEVFSNAME, &ops, + THIS_MODULE)) == NULL) goto error; /* allocate memory for our device state and intialize it */ @@ -981,8 +934,8 @@ error: if (cardstate) static void __exit usb_gigaset_exit(void) { gigaset_blockdriver(driver); /* => probe will fail - * => no gigaset_start any more - */ + * => no gigaset_start any more + */ gigaset_shutdown(cardstate); /* from now on, no isdn callback should be possible */ |