From f11777d1a323daf29ff336e6a5aed84d8198b360 Mon Sep 17 00:00:00 2001 From: markster Date: Sat, 29 Jun 2002 18:08:17 +0000 Subject: Version 0.2.0 from FTP git-svn-id: http://svn.digium.com/svn/zaptel/trunk@89 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- Makefile | 59 +++++++++++++-- wcfxo.c | 240 ++++++++++++++++++++++++++++++++++++++----------------------- wcfxsusb.c | 12 ++-- 3 files changed, 213 insertions(+), 98 deletions(-) diff --git a/Makefile b/Makefile index 7502f18..fb592cb 100755 --- a/Makefile +++ b/Makefile @@ -15,14 +15,32 @@ DEFAULTZONE=0 KINCLUDES=$(shell if [ -d /usr/src/linux-2.4/include ]; then echo /usr/src/linux-2.4/include ; else echo /usr/src/linux/include ; fi) CFLAGS+=-I. -O4 -g -Wall -DBUILDING_TONEZONE #-DTONEZONE_DRIVER +CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) LCFLAGS=-fPIC $(CFLAGS) -DBUILDING_TONEZONE KFLAGS+=-I/usr/src/linux-2.4/include -O6 KFLAGS+=-DMODULE -D__KERNEL__ -DEXPORT_SYMTAB -I/usr/src/linux/drivers/net \ -Wall -I. -Wstrict-prototypes -fomit-frame-pointer -I/usr/src/linux/drivers/net/wan -I /usr/src/linux/include -I/usr/src/linux/include/net KFLAGS+=$(shell [ -f $(KINCLUDES)/linux/modversions.h ] && echo "-DMODVERSIONS -include $(KINCLUDES)/linux/modversions.h") +KFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-msoft-float -fsigned-char"; fi) # # Features # +# +# Define CONFIG_CALC_XLAW if you have a small number of channels and/or +# a small level 2 cache, to optimize for few channels +# +#KFLAGS+=-DCONFIG_CALC_XLAW +# +# Define if you want MMX optimizations in zaptel +# +#KFLAGS+=-DCONFIG_ZAPTEL_MMX +# +# Pick your echo canceller: MARK, STEVE, or STEVE2 :) +# +KFLAGS+=-DECHO_CAN_STEVE +#KFLAGS+=-DECHO_CAN_STEVE2 +#KFLAGS+=-DECHO_CAN_MARK +# # Uncomment -DCONFIG_ZAPATA_NET to enable SyncPPP, CiscoHDLC, and Frame Relay # support. # @@ -30,7 +48,7 @@ KFLAGS+=$(shell [ -f $(KINCLUDES)/linux/modversions.h ] && echo "-DMODVERSIONS - # # Uncomment for Generic PPP support (i.e. ZapRAS) # -#KFLAGS+=-DCONFIG_ZAPATA_PPP +KFLAGS+=-DCONFIG_ZAPATA_PPP # # ISA Defaults can be set here. # @@ -45,7 +63,7 @@ KFLAGS+=-DDEFAULT_TONE_ZONE=$(DEFAULTZONE) KFLAGS+=-DSTANDALONE_ZAPATA CFLAGS+=-DSTANDALONE_ZAPATA -MODCONF=$(shell if [ -f /etc/modules.conf ]; then echo /etc/modules.conf; else echo /etc/conf.modules ; fi) +MODCONF=$(shell if [ -d /etc/modutils ]; then echo "/etc/modutils/zaptel"; elif [ -f /etc/modules.conf ]; then echo /etc/modules.conf; else echo /etc/conf.modules ; fi) TZOBJS=zonedata.lo tonezone.lo LIBTONEZONE=libtonezone.so.1.0 @@ -57,7 +75,7 @@ ZTTOOL=$(shell if [ -f /usr/include/newt.h ]; then echo zttool; fi) PRIMARY=torisa #PRIMARY=wcfxo -all: $(MODULES) ztcfg torisatool fxstest makefw $(ZTTOOL) sethdlc +all: $(MODULES) ztcfg torisatool fxstest makefw ztmonitor ztspeed $(ZTTOOL) devel: tor2ee @@ -66,7 +84,7 @@ tests: patgen pattest tor2.o: tor2.c tor2-hw.h tor.h tor2fw.h zaptel.h gcc $(KFLAGS) -c tor2.c -zaptel.o: zaptel.c zaptel.h digits.h +zaptel.o: zaptel.c zaptel.h digits.h arith.h gcc $(KFLAGS) -c zaptel.c torisa.o: torisa.c zaptel.h torisa.h @@ -120,9 +138,23 @@ zaptel.c: tones.h zttool.o: zttool.c zaptel.h +ztmonitor.o: ztmonitor.c zaptel.h + +ztspeed.o: ztspeed.c + $(CC) -c ztspeed.c + zttool: zttool.o $(CC) -o zttool zttool.o -lnewt +ztmonitor: ztmonitor.o + $(CC) -o ztmonitor ztmonitor.o + +ztcat: ztcat.o + $(CC) -o ztcat ztcat.o -ltonezone + +ztspeed: ztspeed.o + $(CC) -o ztspeed ztspeed.o + $(LIBTONEZONE): $(TZOBJS) $(CC) -shared -Wl,-soname,libtonezone.so.1 -lm -o $@ $(TZOBJS) /sbin/ldconfig -n . @@ -150,7 +182,7 @@ devices: install: all devices install -m 755 ztcfg /sbin - install -m 755 sethdlc /sbin + if [ -f sethdlc ]; then install -m 755 sethdlc /sbin ; fi if [ -f zttool ]; then install -m 755 zttool /sbin; fi mkdir -p /lib/modules/`uname -r`/misc for x in $(MODULES); do \ @@ -193,9 +225,26 @@ install: all devices if ! grep "post-install wct1xxp" $(MODCONF); then \ echo "post-install wct1xxp /sbin/ztcfg" >> $(MODCONF); \ fi + if [ -d /etc/modutils ]; then \ + /sbin/update-modules ; \ + fi /sbin/depmod -a [ -f /etc/zaptel.conf ] || install -m 644 zaptel.conf.sample /etc/zaptel.conf +config: + if [ -d /etc/rc.d/init.d ]; then \ + install -m 755 zaptel.init /etc/rc.d/init.d/zaptel; \ + chkconfig --add zaptel; \ + elif [ -d /etc/init.d ]; then \ + install -m 755 zaptel.init /etc/init.d/zaptel; \ + fi + if [ ! -f /etc/sysconfig/zaptel ]; then \ + install -m 644 zaptel.sysconfig /etc/sysconfig/zaptel; \ + fi + if [ -d /etc/sysconfig/network-scripts ]; then \ + install -m 755 ifup-hdlc /etc/sysconfig/network-scripts/ifup-hdlc; \ + fi + clean: rm -f torisatool makefw tor2fw.h rm -f zttool diff --git a/wcfxo.c b/wcfxo.c index b878467..1b020fd 100755 --- a/wcfxo.c +++ b/wcfxo.c @@ -12,15 +12,15 @@ * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. - * + * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * + * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ @@ -37,9 +37,10 @@ #include #endif -/* RING detection fiddling */ -#define RING_INC 10 -#define RING_MAX 50 +/* Uncomment to enable tasklet handling in the FXO driver. Not recommended + in general, but may improve interactive performance */ + +/* #define ENABLE_TASKLETS */ #define WC_MAX_IFACES 128 @@ -67,7 +68,11 @@ #define FLAG_READ 2 #define RING_DEBOUNCE 64 /* Ringer Debounce (in ms) */ -#define BATT_DEBOUNCE 8 /* Battery debounce (in ms) */ +#define BATT_DEBOUNCE 80 /* Battery debounce (in ms) */ + +#define MINPEGTIME 10 * 8 /* 30 ms peak to peak gets us no more than 100 Hz */ +#define PEGTIME 50 * 8 /* 50ms peak to peak gets us rings of 10 Hz or more */ +#define PEGCOUNT 5 /* 5 cycles of pegging means RING */ struct reg { int flags; @@ -90,11 +95,13 @@ struct wcfxo { int flags; int freeregion; int ring; + int offhook; int battery; int wregcount; int readpos; int rreadpos; - int ringdebounce; + unsigned int pegtimer; + int pegcount; int battdebounce; int nobatttimer; int allread; @@ -105,6 +112,7 @@ struct wcfxo { /* Up to 6 register can be written at a time */ struct reg regs[ZT_CHUNKSIZE]; struct reg oldregs[ZT_CHUNKSIZE]; + unsigned char lasttx[ZT_CHUNKSIZE]; /* Up to 32 registers of whatever we most recently read */ unsigned char readregs[32]; unsigned long ioaddr; @@ -112,6 +120,15 @@ struct wcfxo { dma_addr_t writedma; volatile int *writechunk; /* Double-word aligned write memory */ volatile int *readchunk; /* Double-word aligned read memory */ +#ifdef ENABLE_TASKLETS + int taskletrun; + int taskletsched; + int taskletpending; + int taskletexec; + int txerrors; + int ints; + struct tasklet_struct wcfxo_tlet; +#endif }; #define FLAG_INVERTSER (1 << 0) @@ -124,8 +141,9 @@ struct wcfxo_desc { int flags; }; + static struct wcfxo_desc wcfxo = { "Wildcard Prototype", 0}; -static struct wcfxo_desc wcx100p = { "Wildcard X100P", +static struct wcfxo_desc wcx100p = { "Wildcard X100P", FLAG_INVERTSER | FLAG_USE_XTAL | FLAG_DOUBLE_CLOCK }; static struct wcfxo *ifaces[WC_MAX_IFACES]; @@ -142,23 +160,37 @@ static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) int x; int written=0; unsigned short cmd; - if (ints & 0x01) + + /* if nothing to transmit, have to do the zt_transmit() anyway */ + if (!(ints & 3)) { + /* Calculate Transmission */ + zt_transmit(&wc->span); + return; + } + + /* Remember what it was we just sent */ + memcpy(wc->lasttx, wc->chan.writechunk, ZT_CHUNKSIZE); + + if (ints & 0x01) { /* Write is at interrupt address. Start writing from normal offset */ writechunk = wc->writechunk; - else + } else { writechunk = wc->writechunk + ZT_CHUNKSIZE * 2; - /* Calculate Transmission */ + } + zt_transmit(&wc->span); for (x=0;xflags & FLAG_INVERTSER) - writechunk[x << 1] = - ~((unsigned short)(ZT_MULAW(wc->chan.writechunk[x]))| 0x1) << 16; + if (wc->flags & FLAG_INVERTSER) + writechunk[x << 1] = cpu_to_le32( + ~((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 + ); else - writechunk[x << 1] = - ((unsigned short)(ZT_MULAW(wc->chan.writechunk[x]))| 0x1) << 16; - + writechunk[x << 1] = cpu_to_le32( + ((unsigned short)(ZT_XLAW(wc->chan.writechunk[x], (&wc->chan)))| 0x1) << 16 + ); + /* We always have a command to follow our signal */ if (!wc->regs[x].flags) { /* Fill in an empty register command with a read for a potentially useful register */ @@ -172,7 +204,7 @@ static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) } } - /* Prepare the command to follow it */ + /* Prepare the command to follow it */ switch(wc->regs[x].flags) { case FLAG_READ: cmd = (wc->regs[x].reg | 0x20) << 8; @@ -189,9 +221,9 @@ static inline void wcfxo_transmitprep(struct wcfxo *wc, unsigned char ints) } /* Setup the write chunk */ if (wc->flags & FLAG_INVERTSER) - writechunk[(x << 1) + 1] = ~(cmd << 16); + writechunk[(x << 1) + 1] = cpu_to_le32(~(cmd << 16)); else - writechunk[(x << 1) + 1] = cmd << 16; + writechunk[(x << 1) + 1] = cpu_to_le32(cmd << 16); } if (written) wc->readpos = 0; @@ -211,24 +243,29 @@ static inline void wcfxo_receiveprep(struct wcfxo *wc, unsigned char ints) int x; int realreg; int realval; - if (ints & 0x08) + int sample; + static int peg = 0; + if (ints & 0x04) /* Read is at interrupt address. Valid data is available at normal offset */ readchunk = wc->readchunk; else readchunk = wc->readchunk + ZT_CHUNKSIZE * 2; + + /* Keep track of how quickly our peg alternates */ + wc->pegtimer+=ZT_CHUNKSIZE; for (x=0;xoldregs[x].flags == FLAG_READ && !wc->ignoreread) { - realreg = wecareregs[(wc->regs[x].index + wc->regoffset) % - (sizeof(wecareregs) / sizeof(wecareregs[0]))]; - realval = (readchunk[(x << 1) +wc->alt] >> 16) & 0xff; + realreg = wecareregs[(wc->regs[x].index + wc->regoffset) % + (sizeof(wecareregs) / sizeof(wecareregs[0]))]; + realval = (le32_to_cpu(readchunk[(x << 1) +wc->alt]) >> 16) & 0xff; if ((realval == 0x89) && (realreg != 0x9)) { /* Some sort of slippage, correct for it */ while(realreg != 0x9) { /* Find register 9 */ - realreg = wecareregs[(wc->regs[x].index + ++wc->regoffset) % - (sizeof(wecareregs) / sizeof(wecareregs[0]))]; + realreg = wecareregs[(wc->regs[x].index + ++wc->regoffset) % + (sizeof(wecareregs) / sizeof(wecareregs[0]))]; wc->regoffset = wc->regoffset % (sizeof(wecareregs) / sizeof(wecareregs[0])); } if (debug) @@ -237,13 +274,67 @@ static inline void wcfxo_receiveprep(struct wcfxo *wc, unsigned char ints) /* Receive into the proper register */ wc->readregs[realreg] = realval; } - wc->chan.readchunk[x] = ZT_LIN2MU(((short)(readchunk[(x << 1) + (1 - wc->alt)] >> 16))); + /* Look for pegging to indicate ringing */ + sample = (short)(le32_to_cpu(readchunk[(x << 1) + (1 - wc->alt)]) >> 16); + if ((sample > 32000) && (peg != 1)) { + if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) + wc->pegcount++; + wc->pegtimer = 0; + peg = 1; + } else if ((sample < -32000) && (peg != -1)) { + if ((wc->pegtimer < PEGTIME) && (wc->pegtimer > MINPEGTIME)) + wc->pegcount++; + wc->pegtimer = 0; + peg = -1; + } + wc->chan.readchunk[x] = ZT_LIN2X((sample), (&wc->chan)); + } + if (wc->pegtimer > PEGTIME) { + /* Reset pegcount if our timer expires */ + wc->pegcount = 0; + } + if (!wc->offhook) { + if (!wc->ring && (wc->pegcount > PEGCOUNT)) { + /* It's ringing */ + if (debug) + printk("RING!\n"); + zt_hooksig(&wc->chan, ZT_RXSIG_RING); + wc->ring = 1; + } + if (wc->ring && !wc->pegcount) { + /* No more ring */ + if (debug) + printk("NO RING!\n"); + zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); + wc->ring = 0; + } } if (wc->ignoreread) wc->ignoreread--; + + /* Do the echo cancellation... We are echo cancelling against + what we sent two chunks ago*/ + zt_ec_chunk(&wc->chan, wc->chan.readchunk, wc->lasttx); + + /* Receive the result */ zt_receive(&wc->span); } +#ifdef ENABLE_TASKLETS +static void wcfxo_tasklet(unsigned long data) +{ + struct wcfxo *wc = (struct wcfxo *)data; + wc->taskletrun++; + /* Run tasklet */ + if (wc->taskletpending) { + wc->taskletexec++; + wcfxo_receiveprep(wc, wc->ints); + wcfxo_transmitprep(wc, wc->ints); + } + wc->taskletpending = 0; +} +#endif + static void wcfxo_interrupt(int irq, void *dev_id, struct pt_regs *regs) { struct wcfxo *wc = dev_id; @@ -261,65 +352,33 @@ static void wcfxo_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!ints) return; - if (ints & 0x0f) { + if (ints & 0x0c) { /* if there is a rx interrupt pending */ +#ifdef ENABLE_TASKLETS + wc->ints = ints; + if (!wc->taskletpending) { + wc->taskletpending = 1; + wc->taskletsched++; + tasklet_hi_schedule(&wc->wcfxo_tlet); + } else + wc->txerrors++; +#else wcfxo_receiveprep(wc, ints); + /* transmitprep looks to see if there is anything to transmit + and returns by itself if there is nothing */ wcfxo_transmitprep(wc, ints); +#endif } - + if (ints & 0x10) { printk("PCI Master abort\n"); return; } - + if (ints & 0x20) { printk("PCI Target abort\n"); return; } - if (1 /* !(wc->report % 0xf) */) { - /* Check RING from register and debounce. This is actually - fairly challenging to do, because the ring behavior - seems to differ from one system to another. */ - b = wc->readregs[0x5] & 0x60; -#ifdef DEBUG_RING - if (b != oldb) { - printk("RING Change from %02x to %02x after %d (ringdebounce = %d)\n", oldb, b, oldcnt, wc->ringdebounce); - oldb = b; - oldcnt = 0; - } else - oldcnt++; -#endif - if (!b) { - /* No ring -- subtract one from our counter. We need - a whole bunch of no-rings in a row before we consider - the real ring actually over */ - if (wc->ringdebounce > 0) - wc->ringdebounce -= 1; - if (wc->ring && !wc->ringdebounce) { -#ifndef DEBUG_RING - if (debug) -#endif - printk("NO RING!\n"); - zt_hooksig(&wc->chan, ZT_RXSIG_OFFHOOK); - wc->ring = 0; - } - } else { - /* Ring detected... Increment our counter by a bunch */ - wc->ringdebounce += RING_INC; - /* Max out at RING_MAX. */ - if (wc->ringdebounce > RING_MAX) - wc->ringdebounce = RING_MAX; - if (!wc->ring && (wc->ringdebounce >= RING_MAX)) { - /* Trigger the ring */ -#ifndef DEBUG_RING - if (debug) -#endif - printk("RING!\n"); - zt_hooksig(&wc->chan, ZT_RXSIG_RING); - wc->ring = 1; - } - } - /* Check for BATTERY from register and debounce for 8 ms */ b = wc->readregs[0xc] & 0xf; if (!b) { @@ -327,7 +386,7 @@ static void wcfxo_interrupt(int irq, void *dev_id, struct pt_regs *regs) #if 0 if (wc->battery) printk("Battery loss: %d (%d debounce)\n", b, wc->battdebounce); -#endif +#endif if (wc->battery && !wc->battdebounce) { if (debug) printk("NO BATTERY!\n"); @@ -359,7 +418,7 @@ static void wcfxo_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* It's something else... */ wc->battdebounce = BATT_DEBOUNCE; } - + if (wc->battdebounce) wc->battdebounce--; } @@ -396,7 +455,7 @@ static int wcfxo_close(struct zt_chan *chan) wc->usecount--; MOD_DEC_USE_COUNT; /* If we're dead, release us now */ - if (!wc->usecount && wc->dead) + if (!wc->usecount && wc->dead) wcfxo_release(wc); return 0; } @@ -412,17 +471,19 @@ static int wcfxo_hooksig(struct zt_chan *chan, zt_txsig_t txsig) be done in two steps because of a hardware bug. */ reg = wc->readregs[0x5] & ~0x08; wcfxo_setreg(wc, 0x5, reg); - + reg = reg | 0x1; wcfxo_setreg(wc, 0x5, reg); + wc->offhook = 1; break; case ZT_TXSIG_ONHOOK: /* Put on hook and enable on hook line monitor */ reg = wc->readregs[0x5] & 0xfe; wcfxo_setreg(wc, 0x5, reg); - + reg = reg | 0x08; wcfxo_setreg(wc, 0x5, reg); + wc->offhook = 0; break; default: printk("wcfxo: Can't set tx state to %d\n", txsig); @@ -447,6 +508,9 @@ static int wcfxo_initialize(struct wcfxo *wc) wc->span.close = wcfxo_close; wc->span.flags = ZT_FLAG_RBS; wc->span.deflaw = ZT_LAW_MULAW; +#ifdef ENABLE_TASKLETS + tasklet_init(&wc->wcfxo_tlet, wcfxo_tasklet, (unsigned long)wc); +#endif init_waitqueue_head(&wc->span.maintq); wc->span.pvt = wc; @@ -473,13 +537,13 @@ static int wcfxo_hardware_init(struct wcfxo *wc) } /* Set all to outputs except AUX 4, which is an input */ outb(0xef, wc->ioaddr + WC_AUXC); - + /* Back to normal, with automatic DMA wrap around */ outb(0x01, wc->ioaddr + WC_CNTL); - + /* Make sure serial port and DMA are out of reset */ outb(inb(wc->ioaddr + WC_CNTL) & 0xf9, WC_CNTL); - + /* Configure serial port for MSB->LSB operation */ if (wc->flags & FLAG_DOUBLE_CLOCK) outb(0xc1, wc->ioaddr + WC_SERCTL); @@ -549,7 +613,7 @@ static int wcfxo_init_daa(struct wcfxo *wc) /* Let the reset go */ set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); /* We have a clock at 18.432 Mhz, so N1=1, M1=2, CGM=0 */ wcfxo_setreg(wc, 0x7, 0x0); /* This value is N1 - 1 */ @@ -559,7 +623,7 @@ static int wcfxo_init_daa(struct wcfxo *wc) /* Wait until the PLL's are locked. Time is between 100 uSec and 1 mSec */ set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout(1 + HZ/1000 + (ZT_CHUNKSIZE * HZ) / 800); /* No additional ration is applied to the PLL and faster lock times * are possible */ @@ -576,10 +640,10 @@ static int wcfxo_init_daa(struct wcfxo *wc) /* Wait a couple of jiffies for our writes to finish */ set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); + schedule_timeout(1 + (ZT_CHUNKSIZE * HZ) / 800); /* Didn't get it right. Register 9 is still garbage */ - if (wc->readregs[0x9] != 0x89) + if (wc->readregs[0x9] != 0x89) return -1; #if 0 { int x; diff --git a/wcfxsusb.c b/wcfxsusb.c index 1857f72..7b0f615 100755 --- a/wcfxsusb.c +++ b/wcfxsusb.c @@ -527,7 +527,7 @@ static int wcusb_async_write(struct wc_usb_pvt *p, unsigned char index, unsigned __u16 ind = index; memset(urb, 0, sizeof(urb_t)); - + p->dr.requesttype = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; p->dr.request = REQUEST_NORMAL; p->dr.value = 0; @@ -948,9 +948,9 @@ static void wcusb_do_io(struct wc_usb_pvt *p, struct urb *out, struct urb *in) switch (p->sample) { case STREAM_NORMAL: for (x = 0; x < ZT_CHUNKSIZE; x++) { - p->chan.readchunk[x] = ZT_LIN2MU(ichunk[x]); + p->chan.readchunk[x] = ZT_LIN2MU(le16_to_cpu(ichunk[x])); } - + break; case STREAM_DTMF: for (x = 0; x < ZT_CHUNKSIZE; x++) { @@ -960,12 +960,14 @@ static void wcusb_do_io(struct wc_usb_pvt *p, struct urb *out, struct urb *in) } /* Work with Zaptel now */ + /* XXX Might be able to optimize this some XXX */ + zt_ec_chunk(&p->chan, p->chan.readchunk, p->chan.writechunk); zt_receive(&p->span); zt_transmit(&p->span); /* Fill in transmission info */ for (x = 0; x < ZT_CHUNKSIZE; x++) { - ochunk[x] = ZT_MULAW(p->chan.writechunk[x]); + ochunk[x] = ZT_MULAW(cpu_to_le16(p->chan.writechunk[x])); } /* Transmit the pending outgoing urb */ @@ -1147,7 +1149,7 @@ static int InitPrivate(struct wc_usb_pvt *p) p->datawrite[x].urb.iso_frame_desc[0].offset = 0; p->datawrite[x].urb.transfer_buffer = p->writechunk + ZT_CHUNKSIZE * x; p->datawrite[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; - + } -- cgit v1.2.3