⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 clmodem.c

📁 这个才是朗讯的内置猫驱动
💻 C
字号:
/* *  CLModem v0.3.0 - CLM Linux Kernel Module * *  Copyright (C) 2000  Mikhail Moreyra * *  This file may be redistributed under the terms of the GNU Public *  License. */#include <linux/kernel.h>#include <linux/module.h>#include <linux/pci.h>#include <linux/sched.h>#include <linux/ioport.h>#include <linux/wrapper.h>#include <asm/uaccess.h>#include <linux/tqueue.h>#include <linux/interrupt.h>#include <linux/string.h>#include <linux/ctype.h>#include "clm_config.h"#include "clm_dspdrv.h"#include "clm_modem.h"#include "clmodem.h"#define MODEM_VENDOR_ID         PCI_VENDOR_ID_CIRRUS#define CL_MD5620DT_ID          0x4000MODULE_AUTHOR("Mikhail Moreyra");int BaseIOAddress = CLM_BASE_IO_ADDRESS;int modem_irq = CLM_IRQ;extern volatile int modem_has_connected;#define WAKEUP_CHARS 256static struct tty_driver clm_driver;static int clm_refcount;static struct tty_struct *clm_table[1];static struct termios *clm_termios[1];static struct termios *clm_termios_locked[1];struct tty_struct *clm_tty = NULL;static int clm_opened = 0;static int modem_initialized = 0;volatile int need_write_unblock = 0;char command[64], cmd_resp[64];int cmdp = 0;int resp = 0;void receive_chars(void *);intsetup_clm(void){    struct pci_dev *dev = NULL;        dev = pci_find_device(MODEM_VENDOR_ID, CL_MD5620DT_ID, dev);    if (dev) {        Msg("CL-MD5620DT modem found.\n");#if 0        Dbg("Vendor ID: %x\n", dev->vendor);        Dbg("Device ID: %x\n", dev->device);        Dbg("IRQ      : %d\n", dev->irq);        Dbg("I/O      : %#lx\n", dev->base_address[0]);        Dbg("I/O      : %#lx\n", dev->base_address[1] - 1);  /* ??? */#endif        if (modem_irq != dev->irq) {            Msg("The configured IRQ is wrong. Should be %d\n", dev->irq);            return -1;        }        if (BaseIOAddress != dev->base_address[1]-1) {  /* ? */            Msg("The configured BaseIOAddress is wrong. Should be %#lx\n",                dev->base_address[1] - 1);            return -1;        }        return 1;    } else {        Msg("Couldn't find a CL-MD5620DT modem\n");        return -1;    }}static voidwrite_unblock(void *x){    struct tty_struct *tty = clm_tty;        Dbg("CLM: Unblocking Writing...\n");    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)	(tty->ldisc.write_wakeup)(tty);    wake_up_interruptible(&tty->write_wait);}static voidirq_handler(int irq, void *dev_id, struct pt_regs *regs ){    static struct tq_struct rxtask = {NULL, 0, receive_chars, NULL};    static struct tq_struct txtask = {NULL, 0, write_unblock, NULL};    /* Modem IRQ Handler */    dspdrv_CommRamISR();    /* Sched BH */    if (modem_has_connected && rx_count()) {	queue_task(&rxtask, &tq_immediate);	mark_bh(IMMEDIATE_BH);    }    if (need_write_unblock && (tx_count() < WAKEUP_CHARS)) {	need_write_unblock = 0;	queue_task(&txtask, &tq_immediate);	mark_bh(IMMEDIATE_BH);    }}/***************************************************/static intclm_open(struct tty_struct *tty, struct file *filp){    int dev;        MOD_INC_USE_COUNT;    dev = MINOR(tty->device);    if (dev != 0) {	MOD_DEC_USE_COUNT;	return -ENODEV;    }    Dbg("CLM: clm_open  : (%d)\n", clm_opened);    if (clm_opened > 10)	return -EBUSY;    clm_opened++;    if (!clm_tty)	clm_tty = tty;    else if (clm_tty != tty)	Msg("CLM ERROR: clm_tty doesn't match!\n");    tty->low_latency = 1;	/* low latency  ? */        return 0;}static voidclm_close(struct tty_struct *tty, struct file *filp){    Dbg("CLM: clm_close : (%d)\n", clm_opened-1);    clm_opened--;    if(clm_opened == 0) {	if (modem_initialized) {	    modem_initialized = 0;	    line_io_enable(0);	    set_hook_relay(0);	    if (modem_has_connected) {		end_connection();		print_io_stats(1);	    }	    reset_modem();	}	clm_tty = NULL;    }    MOD_DEC_USE_COUNT;}intcmdr_char(void){    static int i = 0;    if (resp) {	resp--;	return cmd_resp[i++];    } else {	i = 0;	return -1;    }}voidreceive_chars(void *x){    struct tty_struct *tty = clm_tty;    int ch;        while (1) {	if (tty->flip.count >= TTY_FLIPBUF_SIZE) {	    Dbg("CLM: TTY_FLIPBUF_SIZE Full\n");	    break;	}	if (modem_has_connected) {	    if ((ch = read_char()) == -1) break;	} else {	    if ((ch = cmdr_char()) == -1) break;	}	*tty->flip.char_buf_ptr = ch;	*tty->flip.flag_buf_ptr = 0;	tty->flip.char_buf_ptr++;	tty->flip.flag_buf_ptr++;	tty->flip.count++;    }    if (tty->flip.count) {	/* Dbg("CLM: --> RX flip count: %d (rxq: %d - txq: %d)\n", */	/*      tty->flip.count, rx_count(), tx_count()); */    }    tty_flip_buffer_push(tty);}voidset_resp(char *msg){    int i = 0;        while(*msg) {	if (i >= 64) break;	cmd_resp[i++] = *msg;	msg++;    }    resp = i;}voidexec_cmd(void){    int cstat = 0;        if (cmdp < 1) return;    /* Dbg("Executing command\n"); */        if(cmdp >= 63) {	set_resp("\r\nERROR: Command too long\r\n");    } else if(strcmp(command, "INFO") == 0) {	set_resp("CLModem v0.3.0 - Copyright (C) 2000 Mikhail Moreyra\r\n");    } else if(strcmp(command, "INIT") == 0) {	if (!modem_initialized) {	    init_modem();	    modem_initialized = 1;	}	set_volume(VOL_MEDIUM);	set_resp("OK\r\n");    } else if(strcmp(command, "RESET") == 0) {	if (modem_initialized) {	    reset_modem();	    modem_initialized = 0;	}	set_resp("OK\r\n");    } else if(!modem_initialized) {	set_resp("ERROR: Modem not Initialized\r\n");    } else if(strcmp(command, "SPKR ON") == 0) {	set_speaker(SPKR_ON);	set_resp("OK\r\n");    } else if(strcmp(command, "SPKR OFF") == 0) {	set_speaker(SPKR_OFF);	set_resp("OK\r\n");    } else if(strncmp(command, "SPKRVOL ", 8) == 0) {	int vol = 0;	switch (command[8]) {	  case '0': vol = 0; break;	  case '1': vol = 1; break;	  case '2': vol = 2; break;	  case '3': vol = 3; break;	  default: vol = 0;	}	set_volume(vol);	set_resp("OK\r\n");    } else if(strncmp(command, "DIAL ", 5) == 0) {	char *phone;		set_hook_relay(1);	wait_for_dialtone();	phone = (char *) &command[5];	dial_number(TONE_DIALING,  phone);	if (orig_modem_connection()) {	    set_resp("CONNECT\r\n");	} else	    set_resp("ERROR: Couldn't connect\r\n");	cstat = modem_has_connected;    } else	set_resp("ERROR: Unknown Command\r\n");	    modem_has_connected = 0;    receive_chars(0);    modem_has_connected = cstat;    cmdp = 0;}static intclm_write(struct tty_struct *tty, int from_user,	  const unsigned char *buf, int count){    unsigned char c;    int i = 0;        if (!tty) return 0;    /* Dbg("CLM: clm_write (fu: %d, cnt: %d, txq: %d, rxq: %d)\n", */    /*	from_user, count, tx_count(), rx_count()); */    while (count) {	if (from_user) {	    get_user(c, buf++);	} else {	    c = *(buf++);	}		if (modem_has_connected) {	    if (write_char(c) == -1)		break;	    else		i++;	    count--;	} else {  /* Command Mode */	    if (((c == '\r') || (c == '\n')) || (cmdp >= 63)) {		command[cmdp] = '\0';		exec_cmd();		return count;	    }	    command[cmdp++] = toupper(c);	    count--;	    i++;	}    }    if (count) {	Dbg("CLM: Write Error (%d left) will block now\n", count);	need_write_unblock = 1;    }    return i;}static voidclm_put_char(struct tty_struct *tty, unsigned char ch){    Dbg("CLM: clm_put_char\n");    if (write_char(ch) == -1) Dbg("CLM: Couldn't put char\n");}static voidclm_flush_chars(struct tty_struct *tty){    Dbg("CLM: clm_flush_chars\n");}static intclm_write_room(struct tty_struct *tty){    Dbg("CLM: clm_write_room\n");    if (modem_has_connected)	return tx_room();    else	return 63;}static intclm_chars_in_buffer(struct tty_struct *tty){    /* Dbg("CLM: clm_chars_in_buffer\n"); */    return tx_count();}static voidclm_flush_buffer(struct tty_struct *tty){    Dbg("CLM: clm_flush_buffer\n");        wake_up_interruptible(&tty->write_wait);    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && tty->ldisc.write_wakeup)	(tty->ldisc.write_wakeup)(tty);}static intclm_ioctl(struct tty_struct *tty, struct file *file,	  unsigned int cmd, unsigned long arg){    switch(cmd) {      case IOCTL_INIT:	if (!modem_initialized) {	    init_modem();	    modem_initialized = 1;	}	break;      case IOCTL_STAT:	Dbg("CLM_STAT: rxc= %d - txc= %d\n",	    get_rx_count(), get_tx_count());	break;      case IOCTL_DELAY:	delay(arg);	break;      case IOCTL_SET_HOOK:	Dbg("Setting Hook: %ld\n", arg);	set_hook_relay(arg);	break;      case IOCTL_SET_SPKR:	if (!modem_initialized) return 1;	Dbg("Setting Speaker: %ld\n", arg);	set_speaker(arg);	break;      case IOCTL_SET_SPKR_VOL:	if (!modem_initialized) return 1;	Dbg("Setting Speaker Vol: %ld\n", arg);	set_volume(arg);	break;      case IOCTL_WAIT_DIALTONE:	if (!modem_initialized) return 1;	return wait_for_dialtone();	break;      case IOCTL_DIAL_NUMBER:	if (!modem_initialized) return 1;	dial_number(TONE_DIALING, (char *) arg);	break;      case IOCTL_WAIT_ANSWER:	if (!modem_initialized) return 1;	return wait_for_answer();	break;      case IOCTL_WAIT_CARRIER:	if (!modem_initialized) return 1;	return wait_for_carrier();	break;      case IOCTL_ORIG_CONN:	if (!modem_initialized) return 1;	return orig_modem_connection();	break;      default:	/* Dbg("CLM: Unknown device ioctl %x\n", cmd); */	return -ENOIOCTLCMD;	break;    }    return 0;}static voidclm_throttle(struct tty_struct * tty){    Dbg("CLM: clm_throttle not implemented\n");}static voidclm_unthrottle(struct tty_struct * tty){    Dbg("CLM: clm_unthrottle not implemented\n");}static voidclm_send_xchar(struct tty_struct *tty, char ch){    Dbg("CLM: clm_send_xchar\n");}static voidclm_set_termios(struct tty_struct *tty,		struct termios *old_termios){    Dbg("CLM: clm_set_termios not implemented\n");}static voidclm_stop(struct tty_struct *tty){    Dbg("CLM: clm_stop\n");}static voidclm_start(struct tty_struct *tty){    Dbg("CLM: clm_start\n");}static voidclm_hangup(struct tty_struct *tty){    Dbg("CLM: clm_hangup\n");    if (modem_initialized) {	modem_initialized = 0;	line_io_enable(0);	set_hook_relay(0);	if (modem_has_connected) {	    end_connection();	    print_io_stats(1);	}	reset_modem();    }}static voidclm_break(struct tty_struct *tty, int break_state){    Dbg("CLM: clm_break\n");}static voidclm_wait_until_sent(struct tty_struct *tty, int timeout){    Dbg("CLM: clm_wait_until_sent\n");    while(tx_count()) {	delay(10);    }}/**************************************************/intinit_module(void){    Msg("CLModem v0.3.0\n");    Msg("  Copyright (C) 2000  Mikhail Moreyra\n");    Msg("  USE IT AT YOUR OWN RISK!\n");    if (check_region(BaseIOAddress, 256)) {	Msg("CLM ERROR: I/O Ports already in use.\n");	return -1;    }    #ifdef DETECT_PCI_MODEM    if (setup_clm() == -1) return -1;#endif    if (request_irq(modem_irq, irq_handler, 0, "CLModem", NULL)) {        Msg("ERROR: Couldn't get IRQ\n");        return -1;    }    request_region(BaseIOAddress, 256, "CLModem");        memset(&clm_driver, 0, sizeof(struct tty_driver));    clm_driver.magic = TTY_DRIVER_MAGIC;    clm_driver.driver_name = "clmodem";    clm_driver.name = CLM_DEVICE_NAME;    clm_driver.major = CLM_MAJOR_NUM;    clm_driver.minor_start = 0;    clm_driver.num = 1;        /* Just one */    clm_driver.type = TTY_DRIVER_TYPE_SERIAL;    clm_driver.subtype = SERIAL_TYPE_NORMAL;    clm_driver.init_termios = tty_std_termios;    clm_driver.init_termios.c_cflag = B38400 | CS8 | CREAD | HUPCL | CLOCAL;    clm_driver.flags = TTY_DRIVER_REAL_RAW;    clm_driver.refcount = &clm_refcount;    clm_driver.table = clm_table;    clm_driver.termios = clm_termios;    clm_driver.termios_locked = clm_termios_locked;	    clm_driver.open = clm_open;    clm_driver.close = clm_close;    clm_driver.write = clm_write;    clm_driver.put_char = clm_put_char;    clm_driver.flush_chars = clm_flush_chars;    clm_driver.write_room = clm_write_room;    clm_driver.chars_in_buffer = clm_chars_in_buffer;    clm_driver.flush_buffer = clm_flush_buffer;    clm_driver.ioctl = clm_ioctl;    clm_driver.throttle = clm_throttle;    clm_driver.unthrottle = clm_unthrottle;    clm_driver.send_xchar = clm_send_xchar;    clm_driver.set_termios = clm_set_termios;    clm_driver.stop = clm_stop;    clm_driver.start = clm_start;    clm_driver.hangup = clm_hangup;    clm_driver.break_ctl = clm_break;    clm_driver.wait_until_sent = clm_wait_until_sent;        if (tty_register_driver(&clm_driver)) {	Msg("Couldn't register CLM tty driver\n");	return -1;    }        return 0;}voidcleanup_module(void){    int rv;    if ((rv = tty_unregister_driver(&clm_driver)))	Msg("CLModem: failed to unregister CLM driver (%d)\n", rv);    else	Msg("CLModem un-installed\n");    release_region(BaseIOAddress, 256);    free_irq(modem_irq, NULL);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -