summaryrefslogtreecommitdiffstats
path: root/drivers/isdn/gigaset/usb-gigaset.c
diff options
context:
space:
mode:
authorDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
committerDmitry Torokhov <dtor_core@ameritech.net>2006-04-29 01:11:23 -0400
commit7b7e394185014e0f3bd8989cac937003f20ef9ce (patch)
tree3beda5f979bba0aa9822534e239cf1b45f3be69c /drivers/isdn/gigaset/usb-gigaset.c
parentddc5d3414593e4d7ad7fbd33e7f7517fcc234544 (diff)
parent693f7d362055261882659475d2ef022e32edbff1 (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.c455
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 */