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

📄 mct_u232.c

📁 基于S3CEB2410平台LINUX操作系统下 USB驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
			goto exit;		}		port->interrupt_in_urb->dev = port->serial->dev;		retval = usb_submit_urb(port->interrupt_in_urb);		if (retval)			err(" usb_submit_urb(read int) failed");	}exit:	up (&port->sem);		return 0;} /* mct_u232_open */static void mct_u232_close (struct usb_serial_port *port, struct file *filp){	dbg(__FUNCTION__" port %d", port->number);	down (&port->sem);	--port->open_count;	if (port->open_count <= 0) {		if (port->serial->dev) {			/* shutdown our urbs */			usb_unlink_urb (port->write_urb);			usb_unlink_urb (port->read_urb);			usb_unlink_urb (port->interrupt_in_urb);		}		port->active = 0;	}		up (&port->sem);	MOD_DEC_USE_COUNT;} /* mct_u232_close */#ifdef FIX_WRITE_RETURN_CODE_PROBLEM/* The generic routines work fine otherwise */static int mct_u232_write (struct usb_serial_port *port, int from_user,			   const unsigned char *buf, int count){	struct usb_serial *serial = port->serial;	int result, bytes_sent, size;	dbg(__FUNCTION__ " - port %d", port->number);	if (count == 0) {		dbg(__FUNCTION__ " - write request of 0 bytes");		return (0);	}	/* only do something if we have a bulk out endpoint */	if (!serial->num_bulk_out)		return(0);;		/* another write is still pending? */	if (port->write_urb->status == -EINPROGRESS) {		dbg (__FUNCTION__ " - already writing");		return (0);	}			bytes_sent = 0;	while (count > 0) {				down (&port->sem);				size = (count > port->bulk_out_size) ? port->bulk_out_size : count;				usb_serial_debug_data (__FILE__, __FUNCTION__, size, buf);				if (from_user) {			if (copy_from_user(port->write_urb->transfer_buffer, buf, size)) {				up (&port->sem);				return -EFAULT;			}		}		else {			memcpy (port->write_urb->transfer_buffer, buf, size);		}				/* set up our urb */		FILL_BULK_URB(port->write_urb, serial->dev,			      usb_sndbulkpipe(serial->dev,					      port->bulk_out_endpointAddress),			      port->write_urb->transfer_buffer, size,			      ((serial->type->write_bulk_callback) ?			       serial->type->write_bulk_callback :			       mct_u232_write_bulk_callback),			      port);				/* send the data out the bulk port */		result = usb_submit_urb(port->write_urb);		if (result) {			err(__FUNCTION__			    " - failed submitting write urb, error %d", result);			up (&port->sem);			return result;		}		up (&port->sem);		bytes_sent += size;		if (write_blocking)			interruptible_sleep_on(&port->write_wait);		else			break;		buf += size;		count -= size;	}		return bytes_sent;} /* mct_u232_write */static void mct_u232_write_bulk_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct usb_serial *serial = port->serial;       	struct tty_struct *tty = port->tty;	dbg(__FUNCTION__ " - port %d", port->number);		if (!serial) {		dbg(__FUNCTION__ " - bad serial pointer, exiting");		return;	}	if (urb->status) {		dbg(__FUNCTION__ " - nonzero write bulk status received: %d",		    urb->status);		return;	}	if (write_blocking) {		wake_up_interruptible(&port->write_wait);		if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&		    tty->ldisc.write_wakeup)			(tty->ldisc.write_wakeup)(tty);		wake_up_interruptible(&tty->write_wait);			} else {		/* from generic_write_bulk_callback */		queue_task(&port->tqueue, &tq_immediate);		mark_bh(IMMEDIATE_BH);	}	return;} /* mct_u232_write_bulk_callback */#endifstatic void mct_u232_read_int_callback (struct urb *urb){	struct usb_serial_port *port = (struct usb_serial_port *)urb->context;	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;	struct usb_serial *serial = port->serial;	struct tty_struct *tty;	unsigned char *data = urb->transfer_buffer;        dbg(__FUNCTION__ " - port %d", port->number);	/* The urb might have been killed. */        if (urb->status) {                dbg(__FUNCTION__ " - nonzero read bulk status received: %d",		    urb->status);                return;        }	if (!serial) {		dbg(__FUNCTION__ " - bad serial pointer, exiting");		return;	}		usb_serial_debug_data (__FILE__, __FUNCTION__, urb->actual_length, data);	/*	 * Work-a-round: handle the 'usual' bulk-in pipe here	 */	if (urb->transfer_buffer_length > 2) {		int i;		tty = port->tty;		if (urb->actual_length) {			for (i = 0; i < urb->actual_length ; ++i) {				tty_insert_flip_char(tty, data[i], 0);			}			tty_flip_buffer_push(tty);		}		/* INT urbs are automatically re-submitted */		return;	}		/*	 * The interrupt-in pipe signals exceptional conditions (modem line	 * signal changes and errors). data[0] holds MSR, data[1] holds LSR.	 */	priv->last_msr = data[MCT_U232_MSR_INDEX];		/* Record Control Line states */	mct_u232_msr_to_state(&priv->control_state, priv->last_msr);#if 0	/* Not yet handled. See belin_sa.c for further information */	/* Now to report any errors */	priv->last_lsr = data[MCT_U232_LSR_INDEX];	/*	 * fill in the flip buffer here, but I do not know the relation	 * to the current/next receive buffer or characters.  I need	 * to look in to this before committing any code.	 */	if (priv->last_lsr & MCT_U232_LSR_ERR) {		tty = port->tty;		/* Overrun Error */		if (priv->last_lsr & MCT_U232_LSR_OE) {		}		/* Parity Error */		if (priv->last_lsr & MCT_U232_LSR_PE) {		}		/* Framing Error */		if (priv->last_lsr & MCT_U232_LSR_FE) {		}		/* Break Indicator */		if (priv->last_lsr & MCT_U232_LSR_BI) {		}	}#endif	/* INT urbs are automatically re-submitted */} /* mct_u232_read_int_callback */static void mct_u232_set_termios (struct usb_serial_port *port,				  struct termios *old_termios){	struct usb_serial *serial = port->serial;	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;	unsigned int iflag = port->tty->termios->c_iflag;	unsigned int old_iflag = old_termios->c_iflag;	unsigned int cflag = port->tty->termios->c_cflag;	unsigned int old_cflag = old_termios->c_cflag;		/*	 * Update baud rate	 */	if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {	        /* reassert DTR and (maybe) RTS on transition from B0 */		if( (old_cflag & CBAUD) == B0 ) {			dbg(__FUNCTION__ ": baud was B0");			priv->control_state |= TIOCM_DTR;			/* don't set RTS if using hardware flow control */			if (!(old_cflag & CRTSCTS)) {				priv->control_state |= TIOCM_RTS;			}			mct_u232_set_modem_ctrl(serial, priv->control_state);		}				switch(cflag & CBAUD) {		case B0: /* handled below */			break;		case B300: mct_u232_set_baud_rate(serial, 300);			break;		case B600: mct_u232_set_baud_rate(serial, 600);			break;		case B1200: mct_u232_set_baud_rate(serial, 1200);			break;		case B2400: mct_u232_set_baud_rate(serial, 2400);			break;		case B4800: mct_u232_set_baud_rate(serial, 4800);			break;		case B9600: mct_u232_set_baud_rate(serial, 9600);			break;		case B19200: mct_u232_set_baud_rate(serial, 19200);			break;		case B38400: mct_u232_set_baud_rate(serial, 38400);			break;		case B57600: mct_u232_set_baud_rate(serial, 57600);			break;		case B115200: mct_u232_set_baud_rate(serial, 115200);			break;		default: err("MCT USB-RS232 converter: unsupported baudrate request, using default of 9600");			mct_u232_set_baud_rate(serial, 9600); break;		}		if ((cflag & CBAUD) == B0 ) {			dbg(__FUNCTION__ ": baud is B0");			/* Drop RTS and DTR */			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);        		mct_u232_set_modem_ctrl(serial, priv->control_state);		}	}	/*	 * Update line control register (LCR)	 */	if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))	    || (cflag & CSIZE) != (old_cflag & CSIZE)	    || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {				priv->last_lcr = 0;		/* set the parity */		if (cflag & PARENB)			priv->last_lcr |= (cflag & PARODD) ?				MCT_U232_PARITY_ODD : MCT_U232_PARITY_EVEN;		else			priv->last_lcr |= MCT_U232_PARITY_NONE;		/* set the number of data bits */		switch (cflag & CSIZE) {		case CS5:			priv->last_lcr |= MCT_U232_DATA_BITS_5; break;		case CS6:			priv->last_lcr |= MCT_U232_DATA_BITS_6; break;		case CS7:			priv->last_lcr |= MCT_U232_DATA_BITS_7; break;		case CS8:			priv->last_lcr |= MCT_U232_DATA_BITS_8; break;		default:			err("CSIZE was not CS5-CS8, using default of 8");			priv->last_lcr |= MCT_U232_DATA_BITS_8;			break;		}		/* set the number of stop bits */		priv->last_lcr |= (cflag & CSTOPB) ?			MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1;		mct_u232_set_line_ctrl(serial, priv->last_lcr);	}		/*	 * Set flow control: well, I do not really now how to handle DTR/RTS.	 * Just do what we have seen with SniffUSB on Win98.	 */	if( (iflag & IXOFF) != (old_iflag & IXOFF)	    || (iflag & IXON) != (old_iflag & IXON)	    ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {				/* Drop DTR/RTS if no flow control otherwise assert */		if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )			priv->control_state |= TIOCM_DTR | TIOCM_RTS;		else			priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);		mct_u232_set_modem_ctrl(serial, priv->control_state);	}} /* mct_u232_set_termios */static void mct_u232_break_ctl( struct usb_serial_port *port, int break_state ){	struct usb_serial *serial = port->serial;	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;	unsigned char lcr = priv->last_lcr;	dbg (__FUNCTION__ "state=%d", break_state);	if (break_state)		lcr |= MCT_U232_SET_BREAK;	mct_u232_set_line_ctrl(serial, lcr);} /* mct_u232_break_ctl */static int mct_u232_ioctl (struct usb_serial_port *port, struct file * file,			   unsigned int cmd, unsigned long arg){	struct usb_serial *serial = port->serial;	struct mct_u232_private *priv = (struct mct_u232_private *)port->private;	int mask;		dbg (__FUNCTION__ "cmd=0x%x", cmd);	/* Based on code from acm.c and others */	switch (cmd) {	case TIOCMGET:		return put_user(priv->control_state, (unsigned long *) arg);		break;	case TIOCMSET: /* Turns on and off the lines as specified by the mask */	case TIOCMBIS: /* turns on (Sets) the lines as specified by the mask */	case TIOCMBIC: /* turns off (Clears) the lines as specified by the mask */		if (get_user(mask, (unsigned long *) arg))			return -EFAULT;		if ((cmd == TIOCMSET) || (mask & TIOCM_RTS)) {			/* RTS needs set */			if( ((cmd == TIOCMSET) && (mask & TIOCM_RTS)) ||			    (cmd == TIOCMBIS) )				priv->control_state |=  TIOCM_RTS;			else				priv->control_state &= ~TIOCM_RTS;		}		if ((cmd == TIOCMSET) || (mask & TIOCM_DTR)) {			/* DTR needs set */			if( ((cmd == TIOCMSET) && (mask & TIOCM_DTR)) ||			    (cmd == TIOCMBIS) )				priv->control_state |=  TIOCM_DTR;			else				priv->control_state &= ~TIOCM_DTR;		}		mct_u232_set_modem_ctrl(serial, priv->control_state);		break;						case TIOCMIWAIT:		/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/		/* TODO */		return( 0 );	case TIOCGICOUNT:		/* return count of modemline transitions */		/* TODO */		return 0;	default:		dbg(__FUNCTION__ ": arg not supported - 0x%04x",cmd);		return(-ENOIOCTLCMD);		break;	}	return 0;} /* mct_u232_ioctl */static int __init mct_u232_init (void){	usb_serial_register (&mct_u232_device);	usb_serial_register (&mct_u232_sitecom_device);	usb_serial_register (&mct_u232_du_h3sp_device);	info(DRIVER_VERSION ":" DRIVER_DESC);	return 0;}static void __exit mct_u232_exit (void){	usb_serial_deregister (&mct_u232_device);	usb_serial_deregister (&mct_u232_sitecom_device);	usb_serial_deregister (&mct_u232_du_h3sp_device);}module_init (mct_u232_init);module_exit(mct_u232_exit);MODULE_AUTHOR( DRIVER_AUTHOR );MODULE_DESCRIPTION( DRIVER_DESC );MODULE_LICENSE("GPL");#ifdef FIX_WRITE_RETURN_CODE_PROBLEMMODULE_PARM(write_blocking, "i");MODULE_PARM_DESC(write_blocking, 		 "The write function will block to write out all data");#endifMODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debug enabled or not");

⌨️ 快捷键说明

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