summaryrefslogtreecommitdiff
path: root/wcusb.c
diff options
context:
space:
mode:
authormarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-12-02 03:02:14 +0000
committermarkster <markster@5390a7c7-147a-4af0-8ec9-7488f05a26cb>2002-12-02 03:02:14 +0000
commitc15162e2ccf8747e2cb0af39a1ba04955701f15d (patch)
treea81e94dd59e92e6739540b7cbdea4bb23180e750 /wcusb.c
parent70c27a0518c63a604b3e4ab78ebc717b009d1b52 (diff)
Version 0.3.3 from FTP
git-svn-id: http://svn.digium.com/svn/zaptel/trunk@133 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'wcusb.c')
-rwxr-xr-xwcusb.c93
1 files changed, 62 insertions, 31 deletions
diff --git a/wcusb.c b/wcusb.c
index a04d157..cd51f32 100755
--- a/wcusb.c
+++ b/wcusb.c
@@ -28,7 +28,7 @@
this is set, we only transit on hook for some time after a ring
(POWERSAVE_TIMEOUT) */
-#define PROSLIC_POWERSAVE
+/* #define PROSLIC_POWERSAVE */
#define POWERSAVE_TIME 4000
#include <linux/kernel.h>
@@ -113,7 +113,6 @@ static alpha indirect_regs[] =
};
static int debug = 0;
-static int devcount = 0;
#define FLAG_FLIP_RELAYS (1 << 0)
@@ -811,7 +810,7 @@ static void wcusb_read_complete(struct urb *q)
switch (p->sample) {
case STREAM_NORMAL:
for (x = 0; x < ZT_CHUNKSIZE; x++) {
- p->chan.readchunk[x] = ZT_LIN2MU(chunk[x]);
+ p->chan.readchunk[x] = ZT_LIN2MU(le16_to_cpu(chunk[x]));
}
break;
case STREAM_DTMF:
@@ -867,7 +866,7 @@ static void wcusb_write_complete(struct urb *q)
zt_transmit(&p->span);
for (x = 0; x < ZT_CHUNKSIZE; x++) {
- chunk[x] = ZT_MULAW(p->chan.writechunk[x]);
+ chunk[x] = cpu_to_le16(ZT_MULAW(p->chan.writechunk[x]));
}
q->dev = p->dev;
@@ -1054,6 +1053,7 @@ static int wc_usb_close(struct zt_chan *chan)
/* Someone unplugged us while we were running, so now
that the program exited, we can release our resources */
zt_unregister(&p->span);
+ ifaces[p->pos] = NULL;
if (p->pvt_data)
kfree(p->pvt_data);
kfree(p);
@@ -1062,16 +1062,20 @@ static int wc_usb_close(struct zt_chan *chan)
return 0;
}
-static struct wc_usb_pvt *wc_detect_device(struct usb_device *dev)
+static struct wc_usb_pvt *wc_detect_device(struct usb_device *dev, struct wc_usb_pvt *orig)
{
- struct wc_usb_pvt *p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL);
-
+ struct wc_usb_pvt *p;
+
+ p = orig;
if (!p) {
- printk("wcusb: kmalloc failed\n");
- return NULL;
- }
+ p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL);
+ if (!p) {
+ printk("wcusb: kmalloc failed\n");
+ return NULL;
+ }
- memset(p, 0, sizeof(struct wc_usb_pvt));
+ memset(p, 0, sizeof(struct wc_usb_pvt));
+ }
p->dev = dev;
#ifdef PROSLIC_POWERSAVE
@@ -1109,9 +1113,16 @@ static int wc_set_zaptel(struct wc_usb_pvt *p)
{
int x;
- sprintf(p->span.name, "WCUSB/%d", devcount);
- sprintf(p->span.desc,"%s %d", p->span.name, devcount);
- sprintf(p->chan.name, "WCUSB/%d/%d", devcount, 0);
+ for (x = 0; x < WC_MAX_IFACES; x++)
+ if (!ifaces[x]) break;
+ if (x >= WC_MAX_IFACES) {
+ printk("wcusb: Too many interfaces\n");
+ return -1;
+ }
+
+ sprintf(p->span.name, "WCUSB/%d", x);
+ sprintf(p->span.desc,"%s %d", p->span.name, x);
+ sprintf(p->chan.name, "WCUSB/%d/%d", x, 0);
p->chan.sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS; /* We're capabable of both FXOKS and FXOLS */
p->chan.chanpos = 1;
@@ -1122,18 +1133,12 @@ static int wc_set_zaptel(struct wc_usb_pvt *p)
p->span.open = wc_usb_open;
p->span.close = wc_usb_close;
- for (x = 0; x < WC_MAX_IFACES; x++)
- if (!ifaces[x]) break;
- if (x >= WC_MAX_IFACES) {
- printk("wcusb: Too many interfaces\n");
- return -1;
- }
-
- p->pos = x;
- p->span.flags = ZT_FLAG_RBS;
- init_waitqueue_head(&p->span.maintq);
- p->span.pvt = p;
- p->chan.pvt = p;
+ ifaces[x] = p;
+ p->pos = x;
+ p->span.flags = ZT_FLAG_RBS;
+ init_waitqueue_head(&p->span.maintq);
+ p->span.pvt = p;
+ p->chan.pvt = p;
/* Set the stream to just pass the data from the device uninhibited */
p->sample = STREAM_NORMAL;
@@ -1151,7 +1156,25 @@ static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const stru
struct wc_usb_pvt *p = NULL;
struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info;
- if (!(p = wc_detect_device(dev))) {
+ int x;
+ for (x=0;x<WC_MAX_IFACES;x++) {
+ /* Find first dead or empty space */
+ p = ifaces[x];
+ if (!p) {
+ if (debug)
+ printk("Device slot %d is free\n", x);
+ break;
+ }
+ if (p->dead) {
+ if (debug)
+ printk("Device slot %d can be revived\n", x);
+ break;
+ }
+ if (debug)
+ printk("Device slot %d is still in use\n", x);
+ }
+
+ if (!(p = wc_detect_device(dev, p))) {
printk("wcusb: No wcusb devices found\n");
return NULL;
}
@@ -1175,7 +1198,7 @@ static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const stru
flip_relays(p, 1);
}
- if (wc_set_zaptel(p)) {
+ if (!p->dead && wc_set_zaptel(p)) {
printk("wcusb: Error in starting the zaptel stuff\n");
goto cleanup;
}
@@ -1185,9 +1208,16 @@ static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const stru
goto cleanup;
}
- printk("wcusb: Found a %s\n", d->name);
+ if (p->dead)
+ printk("wcusb: Rekindling a %s (%s)\n", d->name, p->span.name);
+ else
+ printk("wcusb: Found a %s (%s)\n", d->name, p->span.name);
- devcount++; /* Increase our device count */
+ /* Reset deadness */
+ p->dead = 0;
+ /* Clear alarms */
+ p->span.alarms = 0;
+ zt_alarm_notify(&p->span);
return p;
cleanup:
@@ -1207,10 +1237,12 @@ static void wc_usb_disconnect(struct usb_device *dev, void *ptr)
struct wc_usb_pvt *p = ptr;
if (ptr) {
StopTransmit(p);
+ p->dev = NULL;
if (!p->usecount) {
zt_unregister(&p->span);
if (p->pvt_data)
kfree(p->pvt_data);
+ ifaces[p->pos] = NULL;
kfree(ptr);
} else {
/* Generate alarm and note that we're dead */
@@ -1219,7 +1251,6 @@ static void wc_usb_disconnect(struct usb_device *dev, void *ptr)
p->dead = 1;
}
}
- devcount--;
printk("wcusb: Removed a Wildcard device\n");
return;
}