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

📄 serial_cnxt.c

📁 一个Linux下的软猫驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
static int cnxt_get_hwinst(char *buf, char **start, off_t offset, int length, int *eof, void *data){    struct cnxt_serial_inst *inst = (struct cnxt_serial_inst *)data;    if(offset)	return 0;    if(length > PAGE_SIZE)	length = PAGE_SIZE;    snprintf(buf, length - 1, "%d-%s\n", inst->devnode->hwInstNum, inst->devnode->hwInstName);    buf[length-1] = '\0';    return strlen(buf);}static int cnxt_get_hwprofile(char *buf, char **start, off_t offset, int length, int *eof, void *data){    struct cnxt_serial_inst *inst = (struct cnxt_serial_inst *)data;    if(offset)	return 0;    if(length > PAGE_SIZE)	length = PAGE_SIZE;    snprintf(buf, length - 1, "%s\n", inst->devnode->hwProfile);    buf[length-1] = '\0';    return strlen(buf);}static int cnxt_get_hwrevision(char *buf, char **start, off_t offset, int length, int *eof, void *data){    struct cnxt_serial_inst *inst = (struct cnxt_serial_inst *)data;    if(offset)	return 0;    if(length > PAGE_SIZE)	length = PAGE_SIZE;    snprintf(buf, length - 1, "%s\n", inst->devnode->hwRevision);    buf[length-1] = '\0';    return strlen(buf);}#ifdef COMCTRL_MONITOR_POUND_UG_SUPPORTstatic int cnxt_get_lastcallstatus(char *page, char **start, off_t offset, int length, int *eof, void *data){    struct cnxt_serial_inst *inst = (struct cnxt_serial_inst *)data;    PORT_MONITOR_DATA monitorData;    int len = PAGE_SIZE;    monitorData.dwSize = len;    monitorData.pBuf = page;    if (cnxt_monitor(inst, COMCTRL_MONITOR_POUND_UG, &monitorData) != COM_STATUS_SUCCESS) {	page[0] = '\0';    } else    	page[len-1] = '\0';    len = strlen(page);    if (len <= offset+length)	*eof = 1;    *start = page + offset;    len -= offset;    if (len > length)        len = length;    if (len < 0)        len = 0;    return len;}#endif /* COMCTRL_MONITOR_POUND_UG_SUPPORT */#endif /* CONFIG_PROC_FS */#ifndef FOUND_UART_REGISTER_PORTstatic DECLARE_MUTEX(cnxt_port_sem);/** *	uart_register_port - register a serial port *      @drv: UART driver *	@port: serial port template * *	Configure the serial port specified by the request. * *	The port is then probed and if necessary the IRQ is autodetected *	If this fails an error is returned. * *	On success the port is ready to use and the line number is returned. */static int uart_register_port(struct uart_driver *drv, struct uart_port *port){	int i;	struct uart_port *uart_port;	int ret = -ENOSPC;	down(&cnxt_port_sem);	for (i = 0; i < NR_PORTS; i++) {		uart_port = &cnxt_ports[i];		if (uart_port->type == PORT_UNKNOWN)			break;	}	if (i < NR_PORTS) {		uart_remove_one_port(drv, uart_port);		uart_port->iobase = port->iobase;		uart_port->membase = port->membase;		uart_port->irq      = port->irq;		uart_port->uartclk  = port->uartclk;		uart_port->iotype   = port->iotype;		uart_port->flags    = port->flags | UPF_BOOT_AUTOCONF;		uart_port->mapbase  = port->mapbase;		if (port->dev)			uart_port->dev = port->dev;		ret = uart_add_one_port(drv, uart_port);		if (ret == 0)			ret = uart_port->line;	}	up(&cnxt_port_sem);	return ret;}/** *	uart_unregister_port - remove a serial port at runtime *      @drv: UART driver *	@line: serial line number * *	Remove one serial port.  This may not be called from interrupt *	context.  We hand the port back to the our control. */static void uart_unregister_port(struct uart_driver *drv, int line){	struct uart_port *uart_port = &cnxt_ports[line];	down(&cnxt_port_sem);	uart_remove_one_port(drv, uart_port);	uart_port->flags = 0;	uart_port->type = PORT_UNKNOWN;	uart_port->iobase = 0;	uart_port->mapbase = 0;	uart_port->membase = 0;	uart_port->dev = NULL;	uart_add_one_port(drv, uart_port);	up(&cnxt_port_sem);}#endif /* FOUND_UART_REGISTER_PORT */int cnxt_serial_add(POS_DEVNODE devnode, unsigned int iobase, void *membase, unsigned int irq, struct module *owner){    struct cnxt_serial_inst *inst = NULL;    int i, r;    struct uart_port port;    PORT_EVENT_HANDLER EvtHandler;    unsigned long flags;    if(!devnode) {	return -EINVAL;    }    for(i = 0; i < NR_PORTS; i++) {	spin_lock_irqsave(&cnxt_serial_inst[i].lock, flags);	if(!cnxt_serial_inst[i].devnode) {	    inst = &cnxt_serial_inst[i];	    inst->devnode = devnode;	    spin_unlock_irqrestore(&cnxt_serial_inst[i].lock, flags);	    break;	}	spin_unlock_irqrestore(&cnxt_serial_inst[i].lock, flags);    }    if(!inst) {	return -ENOSPC;    }    devnode->hwInstNum = i; /* instance number, needed by osnvm */    inst->hcomctrl = ComCtrl_Create();    if(!inst->hcomctrl) {	printk(KERN_DEBUG "%s: ComCtrlCreate failed!\n", __FUNCTION__);	r = -EIO;	goto errout;    }        devnode->hcomctrl = inst->hcomctrl;    if ((r=ComCtrl_Configure(inst->hcomctrl, COMCTRL_CONFIG_DEVICE_ID, devnode))) {	printk(KERN_DEBUG "%s: ComCtrlConfigure DEVICE_ID failed (%d)\n", __FUNCTION__, r);	r = -EIO;	goto errout;    }    inst->port = NULL;    inst->owner = owner;    inst->mctrl_flags = 0;    inst->typestr = kmalloc(strlen(CNXTDRVDSC) + strlen(devnode->hwInstName) + 5, GFP_KERNEL);    if(inst->typestr)	sprintf(inst->typestr, "%s (%s)", CNXTDRVDSC, devnode->hwInstName);    inst->evt_rxchar = 0;    inst->evt_rxbreak = 0;    inst->evt_rxovrn = 0;    inst->evt_txempty = 1;    inst->rxenabled = 0;    inst->txenabled = 0;    inst->readcount = inst->readoffset = 0;    OsThreadScheduleInit(&inst->intr_tqueue, cnxt_intr, inst);    EvtHandler.pfnCallback = (#if (__GNUC__ == 3 && __GNUC_MINOR__ > 1) || __GNUC__ > 3			__shimcall__#endif			void (*) (PVOID pRef, UINT32 dwEventMask)) cnxt_event_handler;    EvtHandler.pRef = inst;    if ((r=ComCtrl_Configure(inst->hcomctrl, COMCTRL_CONFIG_EVENT_HANDLER, &EvtHandler))) {	printk(KERN_DEBUG "%s: ComCtrlConfigure EVENT_HANDLER failed (%d)\n", __FUNCTION__, r);	r = -EIO;	goto errout;    }    if((r=ComCtrl_Open(inst->hcomctrl))) {	printk(KERN_ERR "%s: ComCtrlOpen failed (%d)\n", __FUNCTION__, r);	r = -EIO;	goto errout;    }    inst->mctrl_flags |= TIOCM_DSR; // until comctrl generates events for this    memset(&port, 0, sizeof(port));    port.iobase = iobase;    port.membase = membase;    port.irq = irq;    port.iotype = iobase ? SERIAL_IO_PORT : SERIAL_IO_MEM;    port.uartclk = BASE_BAUD * 16;    port.fifosize = 16;    port.ops = &cnxt_pops;    port.flags = ASYNC_BOOT_AUTOCONF;    if((r=uart_register_port(&cnxt_reg, &port)) < 0) {	inst->mctrl_flags &= ~TIOCM_DSR;	ComCtrl_Close(inst->hcomctrl);	goto errout;    }    if(r != i) {	printk(KERN_WARNING "%s: uart_register_port returned %d, expecting %d\n", __FUNCTION__, r, i);    }#ifdef CONFIG_PROC_FS    if(cnxt_serial_proc_dir) {	char dirname[10];	snprintf(dirname, sizeof(dirname), "%d", i);	inst->proc_unit_dir = proc_mkdir(dirname, cnxt_serial_proc_dir);	if(inst->proc_unit_dir) {	    inst->proc_hwinst = create_proc_read_entry("hwinst", 0, inst->proc_unit_dir, cnxt_get_hwinst, inst);	    inst->proc_hwprofile = create_proc_read_entry("hwprofile", 0, inst->proc_unit_dir, cnxt_get_hwprofile, inst);	    inst->proc_hwrevision = create_proc_read_entry("hwrevision", 0, inst->proc_unit_dir, cnxt_get_hwrevision, inst);#ifdef COMCTRL_MONITOR_POUND_UG_SUPPORT	    inst->proc_lastcallstatus = create_proc_read_entry("lastcallstatus", 0, inst->proc_unit_dir, cnxt_get_lastcallstatus, inst);	}#endif    }#endif /* CONFIG_PROC_FS */    return 0;errout:    if(inst->hcomctrl) {    	ComCtrl_Destroy(inst->hcomctrl);	inst->hcomctrl = NULL;    }    spin_lock_irqsave(&inst->lock, flags);    inst->devnode = NULL;    spin_unlock_irqrestore(&inst->lock, flags);    return r;}int cnxt_serial_remove(POS_DEVNODE devnode){    struct cnxt_serial_inst *inst = NULL;    int i;    unsigned long flags;    if(!devnode) {	return -EINVAL;    }    for(i = 0; i < NR_PORTS; i++) {	spin_lock_irqsave(&cnxt_serial_inst[i].lock, flags);	if(cnxt_serial_inst[i].devnode == devnode) {	    inst = &cnxt_serial_inst[i];	    spin_unlock_irqrestore(&cnxt_serial_inst[i].lock, flags);	    break;	}	spin_unlock_irqrestore(&cnxt_serial_inst[i].lock, flags);    }    if(!inst) {	return -EINVAL;    }    inst->mctrl_flags &= ~TIOCM_DSR;#ifdef CONFIG_PROC_FS#ifdef COMCTRL_MONITOR_POUND_UG_SUPPORT    if(inst->proc_lastcallstatus)	remove_proc_entry("lastcallstatus", inst->proc_unit_dir);#endif    if(inst->proc_hwrevision)	remove_proc_entry("hwrevision", inst->proc_unit_dir);    if(inst->proc_hwprofile)	remove_proc_entry("hwprofile", inst->proc_unit_dir);    if(inst->proc_hwinst)	remove_proc_entry("hwinst", inst->proc_unit_dir);    if(inst->proc_unit_dir) {	char dirname[10];	snprintf(dirname, sizeof(dirname), "%d", i);	remove_proc_entry(dirname, cnxt_serial_proc_dir);    }#endif /* CONFIG_PROC_FS */    uart_unregister_port(&cnxt_reg, i);    if(inst->hcomctrl) {        devnode->hcomctrl = NULL;	ComCtrl_Close(inst->hcomctrl);	ComCtrl_Destroy(inst->hcomctrl);	inst->hcomctrl = NULL;    }    if(inst->typestr) {	kfree(inst->typestr);	inst->typestr = NULL;    }    spin_lock_irqsave(&inst->lock, flags);    inst->devnode = NULL;    spin_unlock_irqrestore(&inst->lock, flags);    return 0;}static int __initcnxt_serial_init(void){	int i, ret;#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	cnxt_reg.normal_major = serialmajor;	cnxt_reg.callout_major = calloutmajor;#else	cnxt_reg.major = serialmajor;	(void)calloutmajor;#endif	if(serialmajor == 0) {		printk(KERN_ERR "%s: serialmajor parameter must be non-null\n", __FUNCTION__);		return -EINVAL;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)	if(calloutmajor == 0) {		printk(KERN_ERR "%s: calloutmajor parameter must be non-null\n", __FUNCTION__);		return -EINVAL;	}	if(serialmajor == calloutmajor) {		printk(KERN_ERR "%s: serialmajor and calloutmajor parameter values must differ\n", __FUNCTION__);		return -EINVAL;	}#endif	if ((ret = uart_init()) != 0) {		return ret;	}	for(i = 0; i < NR_PORTS; i++) {	    spin_lock_init(&cnxt_serial_inst[i].lock);	    cnxt_ports[i].ops = &cnxt_pops; /* uart_register_port() might not set ops */	    cnxt_ports[i].line = i;	}#ifdef CONFIG_PROC_FS	cnxt_serial_proc_dir = proc_mkdir(CNXTTARGET, proc_root_driver);#endif	ret = uart_register_driver(&cnxt_reg);	if(ret) {#ifdef CONFIG_PROC_FS	    if(cnxt_serial_proc_dir)		remove_proc_entry(CNXTTARGET, proc_root_driver);#endif		uart_exit();		return ret;	}#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))	for(i = 0; i < NR_PORTS; i++) {		uart_add_one_port(&cnxt_reg, &cnxt_ports[i]);	}#endif	return ret;}static void __exitcnxt_serial_exit(void){#if !(LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0))	int i;	for(i = 0; i < NR_PORTS; i++) {		uart_remove_one_port(&cnxt_reg, &cnxt_ports[i]);	}#endif	uart_unregister_driver(&cnxt_reg);#ifdef CONFIG_PROC_FS    if(cnxt_serial_proc_dir)	remove_proc_entry(CNXTTARGET, proc_root_driver);#endif	uart_exit();}module_init(cnxt_serial_init);module_exit(cnxt_serial_exit);EXPORT_SYMBOL_NOVERS(cnxt_serial_add);EXPORT_SYMBOL_NOVERS(cnxt_serial_remove);MODULE_AUTHOR("Copyright (C) 2003-2004 Linuxant inc.");MODULE_DESCRIPTION("Virtual serial port driver for Conexant modems");MODULE_LICENSE("GPL\0for files in the \"GPL\" directory; for others, only LICENSE file applies");MODULE_INFO(supported, "yes");#ifdef CNXTSERIAL_INCLUDE_CORE#undef EXPORT_SYMBOL#define EXPORT_SYMBOL(x)#undef MODULE_DESCRIPTION#define MODULE_DESCRIPTION(x)#undef MODULE_LICENSE#define MODULE_LICENSE(x)#undef MODULE_INFO#define MODULE_INFO(x,y)#undef module_init#define module_init(x)#undef module_exit#define module_exit(x)#include "serial_core.c"#endif

⌨️ 快捷键说明

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