📄 wcfxsusb.c
字号:
break; case STREAM_DTMF: for (x = 0; x < ZT_CHUNKSIZE; x++) { p->chan.readchunk[x] = wc_dtmf(p); } break; } /* 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(cpu_to_le16(p->chan.writechunk[x])); } /* Transmit the pending outgoing urb */ if (usb_submit_urb(out)) { printk("wcusb: 'write' urb failed\n"); } else { p->urbcount++; } /* Readsubmit read URB */ if (usb_submit_urb(in)) { printk("wcusb: 'read' urb failed\n"); } else p->urbcount++; /* Clear I/O state */ p->iostate = 0;}static void wcusb_read_complete(struct urb *q){ struct wc_usb_pvt *p = q->context; /* Decrement number of outstanding URB's */ p->urbcount--; if (!p->flags & FLAG_RUNNING) { /* Stop sending URBs since we're not running anymore */ return; } /* Prepare for retransmission */ q->dev = p->dev; if (p->iostate & WC_IO_READ) { static int notify=0; if (!notify) printk("Already ready to read?\n"); notify++; } /* Note that our read is now complete */ p->iostate |= WC_IO_READ; if (IO_READY(p->iostate)) { /* Transmit side is complete, lets go */ wcusb_do_io(p, p->pendingurb, q); } else { /* Let the transmission side know we're ready to go again */ p->pendingurb = q; } if (p->timer && !--p->timer) { if (p->devclass == WC_KEYPAD) { if(debug) printk("Checking keypad\n"); wcusb_check_keypad(p); } else { wcusb_check_interrupt(p); } }#ifdef PROSLIC_POWERSAVE if (p->devclass != WC_KEYPAD) { if (p->lowpowertimer && !--p->lowpowertimer) { /* Switch back into low power mode */ p->idletxhookstate = 1; if (p->txhook == 2) p->newtxhook = p->idletxhookstate; } }#endif return;}static void wcusb_write_complete(struct urb *q){ struct wc_usb_pvt *p = q->context; /* Decrement counter */ p->urbcount--; if (!p->flags & FLAG_RUNNING) { /* Stop sending URBs since we're not running anymore */ return; } if (p->iostate & WC_IO_WRITE) { static int notify=0; if (!notify) printk("Already ready to write?\n"); notify++; } /* Prepare for retransmission */ p->iostate |= WC_IO_WRITE; q->dev = p->dev; if (IO_READY(p->iostate)) { /* Receive is already done, lets go */ wcusb_do_io(p, q, p->pendingurb); } else { /* Let the receive side know we're ready to go again */ p->pendingurb = q; }}static int StopTransmit(struct wc_usb_pvt *p){ p->flags &= ~FLAG_RUNNING; if (p->devclass == WC_KEYPAD) { struct wc_keypad_data *d = p->pvt_data; d->running = 0; } while(p->urbcount) { schedule_timeout(1); } printk("ending transmit\n"); return 0;}static int flip_relays(struct wc_usb_pvt *p, int onoff){ unsigned char ctl; unsigned char data; /* Read data */ if (wcinp(p->dev, 0x12, &data)) return -1; /* Read control */ if (wcinp(p->dev, 0x13, &ctl)) return -1; /* Setup values properly -- Pins AUX3 & AUX4 control the relays */ ctl |= 0x18; if (onoff) { data |= 0x18; } else { data &= 0xe7; } if (wcoutp(p->dev, 0x12, data)) return -1; if (wcoutp(p->dev, 0x13, ctl)) return -1; return 0;}static int InitPrivate(struct wc_usb_pvt *p){ int x; unsigned int readpipe; unsigned int writepipe; /* Endpoint 6 is the wave-in device */ readpipe = usb_rcvisocpipe(p->dev, 0x06); /* Endpoint 7 is the wave-out device */ writepipe = usb_sndisocpipe(p->dev, 0x07); for (x=0;x<2;x++) { p->dataread[x].urb.dev = p->dev; p->dataread[x].urb.pipe = readpipe; p->dataread[x].urb.transfer_flags = USB_ISO_ASAP; p->dataread[x].urb.number_of_packets = 1; p->dataread[x].urb.context = p; p->dataread[x].urb.complete = wcusb_read_complete; p->dataread[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; p->dataread[x].urb.iso_frame_desc[0].offset = 0; p->dataread[x].urb.transfer_buffer = p->readchunk + ZT_CHUNKSIZE * x; p->dataread[x].urb.transfer_buffer_length = ZT_CHUNKSIZE * 2; p->datawrite[x].urb.dev = p->dev; p->datawrite[x].urb.pipe = writepipe; p->datawrite[x].urb.transfer_flags = USB_ISO_ASAP; p->datawrite[x].urb.number_of_packets = 1; p->datawrite[x].urb.context = p; p->datawrite[x].urb.complete = wcusb_write_complete; p->datawrite[x].urb.iso_frame_desc[0].length = ZT_CHUNKSIZE * 2; 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; } return 0;}static int InitTransfer(struct wc_usb_pvt *p){ int x; p->urbcount = 4; p->flags |= FLAG_RUNNING; for (x=0;x<2;x++) { if (usb_submit_urb(&p->dataread[x].urb)) { printk(KERN_ERR "wcusb: Read submit failed\n"); return -1; } if (usb_submit_urb(&p->datawrite[x].urb)) { printk(KERN_ERR "wcusb: Write submit failed\n"); return -1; } } /* Start checking for interrupts */ wcusb_check_interrupt(p); return 0;}static int wc_usb_hooksig(struct zt_chan *chan, zt_txsig_t txsig){ struct wc_usb_pvt *p = chan->pvt; switch (p->devclass) { case WC_PROSLIC:#ifdef PROSLIC_POWERSAVE if (p->txhook == 4) { /* Switching out of ring... Be sure we idle at 2, not 1 at least for a bit so we can transmit caller*ID */ p->idletxhookstate = 2; p->lowpowertimer = POWERSAVE_TIME; }#endif p->txhook = -1; switch(txsig) { case ZT_TXSIG_ONHOOK: switch(chan->sig) { case ZT_SIG_FXOKS: case ZT_SIG_FXOLS: p->newtxhook = p->idletxhookstate; break; case ZT_SIG_FXOGS: p->newtxhook = 3; break; } break; case ZT_TXSIG_OFFHOOK: p->newtxhook = p->idletxhookstate; break; case ZT_TXSIG_START: p->newtxhook = 4; break; case ZT_TXSIG_KEWL: p->newtxhook = 0; break; } case WC_KEYPAD: switch (txsig) { case ZT_TXSIG_ONHOOK: break; case ZT_TXSIG_OFFHOOK: break; case ZT_TXSIG_START: break; case ZT_TXSIG_KEWL: break; } break; } return 0;}static int wc_usb_open(struct zt_chan *chan){ struct wc_usb_pvt *p = chan->pvt; if (p->dead) return -1; switch (p->devclass) { case WC_KEYPAD: p->hookstate = 0; zt_hooksig(&p->chan, ZT_RXSIG_ONHOOK); break; default: break; }#ifndef LINUX26 MOD_INC_USE_COUNT;#endif p->usecount++; return 0;}static int wc_usb_close(struct zt_chan *chan){ struct wc_usb_pvt *p = chan->pvt; p->usecount--; if (!p->usecount && p->dead) { /* 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); }#ifndef LINUX26 MOD_DEC_USE_COUNT;#endif return 0;}static int init_device_pvt(struct wc_usb_pvt *p){ struct usb_device *dev = p->dev; if (dev->descriptor.idProduct == 0xb210) { struct wc_keypad_data *d = kmalloc(sizeof(struct wc_keypad_data), GFP_KERNEL); printk("wcusb: Found a WC Keyed Phone\n"); p->devclass = WC_KEYPAD; if (!d) { printk("wcusb: kmalloc failed in init_device_pvt\n"); return -1; } memset(d, 0, sizeof(struct wc_keypad_data)); p->pvt_data = d; d->count = 0; d->running = 1; d->tone = NULL; return 0; } else { p->pvt_data = NULL; p->devclass = WC_PROSLIC; } return 0;} static void *wc_usb_probe(struct usb_device *dev, unsigned int ifnum, const struct usb_device_id *id){ struct usb_config_descriptor *config = dev->actconfig; struct wc_usb_pvt *p=NULL; struct wc_usb_desc *d = (struct wc_usb_desc *)id->driver_info;#if 0 char auxcon = 0;#endif int x; for (x=0;x<WC_MAX_IFACES;x++) if (!ifaces[x]) break; if (x >= WC_MAX_IFACES) { printk("Too many interfaces\n"); goto fail; } p = kmalloc(sizeof(struct wc_usb_pvt), GFP_KERNEL); if (!p) goto fail; memset(p, 0, sizeof(struct wc_usb_pvt)); p->hardwareflags = d->flags; sprintf(p->span.name, "WCUSB/%d", x); sprintf(p->span.desc,"%s %d", d->name, x); sprintf(p->chan.name, "WCUSB/%d/%d", x, 0);#if 0 /* Make them choose with zaptel.conf */ p->chan.sig = ZT_SIG_FXOKS; /* Assume FXOKS signalling for starters */#endif p->chan.sigcap = ZT_SIG_FXOKS | ZT_SIG_FXOLS | ZT_SIG_FXOGS; /* We're capabable of both FXOKS and FXOLS */ p->chan.chanpos = 1; p->span.deflaw = ZT_LAW_MULAW; p->span.chans = &p->chan; p->span.channels = 1; p->span.hooksig = wc_usb_hooksig; p->span.open = wc_usb_open; p->span.close = wc_usb_close; p->dev = dev; p->pos = x; p->span.flags = ZT_FLAG_RBS; init_waitqueue_head(&p->span.maintq); p->span.pvt = p; p->chan.pvt = p;#ifdef PROSLIC_POWERSAVE /* By default we can't send on hook */ p->idletxhookstate = 1;#else /* By default we can always send on hook */ p->idletxhookstate = 2; #endif ifaces[x] = p; p->sample = STREAM_NORMAL; if (init_device_pvt(p)) { printk(KERN_ERR "wcusb: init_device_pvt failed\n"); goto fail; } if (usb_set_configuration(dev, dev->config[0].bConfigurationValue) < 0) { printk(KERN_ERR "wcusb: set_configuration failed (ConfigValue 0x%x)\n", config->bConfigurationValue); goto fail; } if (InitHardware(p)) { printk(KERN_ERR "wcusb: Hardware initialization failed\n"); goto fail; } if (InitPrivate(p)) { printk(KERN_ERR "wcusb: Unable to initialize private data structure\n"); goto fail; } if (p->hardwareflags & FLAG_FLIP_RELAYS) { flip_relays(p, 1); } if (zt_register(&p->span, 0)) { printk("Unable to register span %s\n", p->span.name); goto fail; } if (InitTransfer(p)) { printk(KERN_ERR "wcusb: Unable to begin data flow\n"); goto fail; } printk("wcusb: Found a %s\n", d->name);#if 0 wcinp(p->dev, 0x13, &auxcon); printk("Register 0x13 is set to %x\n",auxcon);#endif return p;fail: if (x < WC_MAX_IFACES) ifaces[x] = NULL; if (p) { if (p->pvt_data) { kfree(p->pvt_data); } kfree(p); } return NULL;}static void wc_usb_disconnect(struct usb_device *dev, void *ptr){ /* Doesn't handle removal if we're in use right */ struct wc_usb_pvt *p = ptr; if (ptr) { StopTransmit(p); if (!p->usecount) { zt_unregister(&p->span); ifaces[p->pos] = NULL; if (p->pvt_data) kfree(p->pvt_data); kfree(ptr); } else { /* Generate alarm and note that we're dead */ p->span.alarms = ZT_ALARM_RED; zt_alarm_notify(&p->span); p->dead = 1; } } printk("wcusb: Removed a Wildcard device\n"); return;}static struct usb_driver wc_usb_driver ={ name: "wcusb", probe: wc_usb_probe, disconnect: wc_usb_disconnect, fops: NULL, minor: 0, id_table: wc_dev_ids,};static int __init wc_init (void) { int res; res = usb_register(&wc_usb_driver); if (res) return res; printk("Wildcard USB FXS Interface driver registered\n"); return 0;} static void __exit wc_cleanup(void){ usb_deregister(&wc_usb_driver);}MODULE_AUTHOR("Mark Spencer <markster@linux-support.net>");MODULE_DESCRIPTION("Wildcard USB FXS Interface driver");#ifdef MODULE_LICENSEMODULE_LICENSE("GPL");#endifMODULE_PARM(debug, "i");MODULE_DEVICE_TABLE(usb, wc_dev_ids);module_init(wc_init);module_exit(wc_cleanup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -