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

📄 usbdev.c

📁 microwindows移植到S3C44B0的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		send_packet_complete(ep);		// mark a bh to wakeup any tty write system call on the port.		queue_task(&port->send_complete_tq, &tq_immediate);		mark_bh(IMMEDIATE_BH);	}	spin_unlock(&ep->lock);	/*	 * Now check packet receive done (bulk OUT ep). Shouldn't	 * get these, the receive packet complete intr should happen	 * before the DMA done intr occurs.	 */	ep = &port->ep_bulkout;	spin_lock(&ep->lock);	if ((buff_done = get_dma_buffer_done(ep->outdma)) != 0) {		// received a DATAx packet on the port's bulk OUT endpoint		// clear DMA done bit		if (buff_done == DMA_D0)			clear_dma_done0(ep->outdma);		else			clear_dma_done1(ep->outdma);	}	spin_unlock(&ep->lock);}// This ISR needs to handle dma done events for ALL endpoints!static voiddma_done_intr (int irq, void *dev_id, struct pt_regs *regs){	struct usb_serial *serial = (struct usb_serial *) dev_id;	int i;	dma_done_ctrl(serial);	for (i = 0; i < NUM_PORTS; i++)		dma_done_port(&serial->port[i]);}/***************************************************************************** * Here begins the tty driver interface functions *****************************************************************************/static int serial_open(struct tty_struct *tty, struct file *filp){	int portNumber;	struct usb_serial_port *port;	struct usb_serial *serial = &usbserial;	unsigned long flags;	/* initialize the pointer incase something fails */	tty->driver_data = NULL;	MOD_INC_USE_COUNT;	/* set up our port structure making the tty driver remember	   our port object, and us it */	portNumber = MINOR(tty->device) - serial->minor;	port = &serial->port[portNumber];	tty->driver_data = port;	port->tty = tty;	if (port_paranoia_check(port, __FUNCTION__))		return -ENODEV;	dbg(__FUNCTION__ " - port %d", port->number);	spin_lock_irqsave(&port->port_lock, flags);	++port->open_count;	if (!port->active) {		port->active = 1;		/*		 * force low_latency on so that our tty_push actually forces		 * the data through, otherwise it is scheduled, and with high		 * data rates (like with OHCI) data can get lost.		 */		port->tty->low_latency = 1;	}	spin_unlock_irqrestore(&port->port_lock, flags);	return 0;}static void serial_close(struct tty_struct *tty, struct file *filp){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	unsigned long flags;	if (!serial)		return;	dbg(__FUNCTION__ " - port %d", port->number);	if (!port->active) {		dbg(__FUNCTION__ " - port not opened");		return;	}	spin_lock_irqsave(&port->port_lock, flags);	--port->open_count;	if (port->open_count <= 0) {		port->active = 0;		port->open_count = 0;	}	spin_unlock_irqrestore(&port->port_lock, flags);	MOD_DEC_USE_COUNT;}static int serial_write(struct tty_struct *tty, int from_user,			const unsigned char *buf, int count){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	endpoint_t *ep = &port->ep_bulkin;	if (!serial)		return -ENODEV;	if (!port->active) {		dbg(__FUNCTION__ " - port not opened");		return -EINVAL;	}	if (count == 0) {		dbg(__FUNCTION__ " - write request of 0 bytes");		return (0);	}	count = (count > ep->max_pkt_size) ? ep->max_pkt_size : count;	send_packet(ep, (u8 *) buf, count, from_user);	return (count);}static int serial_write_room(struct tty_struct *tty){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	endpoint_t *ep = &port->ep_bulkin;	if (!serial)		return -ENODEV;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return -EINVAL;	}	return ep->max_pkt_size;}static int serial_chars_in_buffer(struct tty_struct *tty){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	endpoint_t *ep = &port->ep_bulkin;	pkt_list_t *list = &ep->inlist;	pkt_t *scan;	unsigned long flags;	int chars = 0;	if (!serial)		return -ENODEV;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return -EINVAL;	}	spin_lock_irqsave(&ep->lock, flags);	for (scan = list->head; scan; scan = scan->next)		chars += scan->size;	spin_unlock_irqrestore(&ep->lock, flags);	return (chars);}static void serial_throttle(struct tty_struct *tty){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	if (!serial)		return;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return;	}	// FIXME: anything to do?}static void serial_unthrottle(struct tty_struct *tty){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	if (!serial)		return;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return;	}	// FIXME: anything to do?}static int serial_ioctl(struct tty_struct *tty, struct file *file,			unsigned int cmd, unsigned long arg){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	if (!serial)		return -ENODEV;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return -ENODEV;	}	// FIXME: need any IOCTLs?	return -ENOIOCTLCMD;}static void serial_set_termios(struct tty_struct *tty, struct termios *old){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	if (!serial)		return;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return;	}	// FIXME: anything to do?}static void serial_break(struct tty_struct *tty, int break_state){	struct usb_serial_port *port =	    (struct usb_serial_port *) tty->driver_data;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	if (!serial)		return;	if (!port->active) {		dbg(__FUNCTION__ " - port not open");		return;	}	// FIXME: anything to do?}static void port_send_complete(void *private){	struct usb_serial_port *port = (struct usb_serial_port *) private;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	struct tty_struct *tty;	dbg(__FUNCTION__ " - port %d", port->number);	if (!serial) {		return;	}	tty = port->tty;	if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&	    tty->ldisc.write_wakeup) {		dbg(__FUNCTION__ " - write wakeup call.");		(tty->ldisc.write_wakeup) (tty);	}	wake_up_interruptible(&tty->write_wait);}static void port_receive_complete(void *private){	struct usb_serial_port *port = (struct usb_serial_port *) private;	struct usb_serial *serial = get_usb_serial(port, __FUNCTION__);	struct tty_struct *tty = port->tty;	pkt_t *pkt;	int i;	dbg(__FUNCTION__ " - port %d", port->number);	if (!serial) {		return;	}	if (!(pkt = receive_packet(&port->ep_bulkout)))		return;	for (i = 0; i < pkt->size; i++) {		/* if we insert more than TTY_FLIPBUF_SIZE characters,		   we drop them. */		if (tty->flip.count >= TTY_FLIPBUF_SIZE) {			tty_flip_buffer_push(tty);		}		/* this doesn't actually push the data through		   unless tty->low_latency is set */		tty_insert_flip_char(tty, pkt->bufptr[i], 0);	}	tty_flip_buffer_push(tty);	// we're done processing the packet, free it	kfree(pkt);}static struct tty_driver serial_tty_driver = {	magic:TTY_DRIVER_MAGIC,	driver_name:"usbdev-serial",	name:"usb/ttsdev/%d",	major:SERIAL_TTY_MAJOR,	minor_start:0,	num:1,	type:TTY_DRIVER_TYPE_SERIAL,	subtype:SERIAL_TYPE_NORMAL,	flags:TTY_DRIVER_REAL_RAW | TTY_DRIVER_NO_DEVFS,	refcount:&serial_refcount,	table:serial_tty,	termios:serial_termios,	termios_locked:serial_termios_locked,	open:serial_open,	close:serial_close,	write:serial_write,	write_room:serial_write_room,	ioctl:serial_ioctl,	set_termios:serial_set_termios,	throttle:serial_throttle,	unthrottle:serial_unthrottle,	break_ctl:serial_break,	chars_in_buffer:serial_chars_in_buffer,};void usbdev_serial_exit(void){	endpoint_t *ep;	int i;	outl_sync(0, USB_DEV_INT_ENABLE);	// disable usb dev ints	outl_sync(0, USB_DEV_ENABLE);	// disable usb dev	// first free all control endpoint resources	ep = &usbserial.ep_ctrl;	free_irq(AU1000_USB_DEV_REQ_INT, &usbserial);	free_irq(AU1000_USB_DEV_SUS_INT, &usbserial);	free_irq(ep->inirq, &usbserial);	//free_irq(ep->outirq, &usbserial);	free_au1000_dma(ep->indma);	free_au1000_dma(ep->outdma);	endpoint_flush(ep);	// now free all port resources	for (i = 0; i < NUM_PORTS; i++) {		// free port's bulk IN endpoint resources		ep = &usbserial.port[i].ep_bulkin;		free_irq(ep->inirq, &usbserial);		free_au1000_dma(ep->indma);		endpoint_flush(ep);		// free port's bulk OUT endpoint resources		ep = &usbserial.port[i].ep_bulkout;		//free_irq(ep->outirq, &usbserial);		free_au1000_dma(ep->outdma);		endpoint_flush(ep);		tty_unregister_devfs(&serial_tty_driver, i);		info("usbdev serial converter now disconnected from ttyUSBdev%d",		     i);	}	kfree(usbserial.str_desc[0]);	tty_unregister_driver(&serial_tty_driver);}int usbdev_serial_init(void){	struct usb_serial_port *port;	endpoint_t *ep;	void *str_desc_buf;	int str_desc_len;	int i;	/* register the tty driver */	serial_tty_driver.init_termios = tty_std_termios;	serial_tty_driver.init_termios.c_cflag =	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;	if (tty_register_driver(&serial_tty_driver)) {		err(__FUNCTION__ ": failed to register tty driver");		return -1;	}	memset(&usbserial, 0, sizeof(struct usb_serial));	usbserial.minor = 0;	usbserial.state = DEFAULT;	usbserial.dev_desc = &dev_desc;	usbserial.if_desc = &if_desc;	usbserial.conf_desc = &config_desc;	/*	 * initialize the string descriptors	 */	/* alloc buffer big enough for all string descriptors */	str_desc_len = string_desc0.bLength;	for (i = 0; i < 5; i++)		str_desc_len += 2 + 2 * strlen(strings[i]);	str_desc_buf = (void *) kmalloc(str_desc_len, ALLOC_FLAGS);	if (!str_desc_buf) {		err(__FUNCTION__ ": failed to alloc string descriptors");		return -1;	}	usbserial.str_desc[0] = (struct usb_string_descriptor *)str_desc_buf;	memcpy(usbserial.str_desc[0], &string_desc0, string_desc0.bLength);	usbserial.str_desc[1] = (struct usb_string_descriptor *)	    (str_desc_buf + string_desc0.bLength);	for (i = 1; i < 6; i++) {		struct usb_string_descriptor *desc = usbserial.str_desc[i];		char *str = strings[i - 1];		int j, str_len = strlen(str);		desc->bLength = 2 + 2 * str_len;		desc->bDescriptorType = USB_DT_STRING;		for (j = 0; j < str_len; j++) {			desc->wData[j] = (u16) str[j];		}		if (i < 5)			usbserial.str_desc[i + 1] =			    (struct usb_string_descriptor *)			    ((u8 *) desc + desc->bLength);	}	// request the USB device transfer complete interrupt	if (request_irq(AU1000_USB_DEV_REQ_INT, req_sus_intr, SA_SHIRQ,			"USBdev req", &usbserial)) {		err("Can't get device request intr\n");		goto err_out;	}	// request the USB device suspend interrupt	if (request_irq(AU1000_USB_DEV_SUS_INT, req_sus_intr, SA_SHIRQ,			"USBdev sus", &usbserial)) {		err("Can't get device suspend intr\n");		goto err_out;	}	// Initialize default control endpoint	ep = &usbserial.ep_ctrl;	spin_lock_init(&ep->lock);	ep->desc = NULL;	// ep0 has no ep descriptor	ep->reg = &ep_reg[0];	ep->max_pkt_size = usbserial.dev_desc->bMaxPacketSize0;	ep->indma = ep->outdma = -1;	if ((ep->indma = request_au1000_dma(ep_dma_id[0].id,					    ep_dma_id[0].str)) < 0) {		err("Can't get %s DMA\n", ep_dma_id[0].str);		goto err_out;	}	if ((ep->outdma = request_au1000_dma(ep_dma_id[1].id,					     ep_dma_id[1].str)) < 0) {		err("Can't get %s DMA\n", ep_dma_id[1].str);		goto err_out;	}	ep->inirq = get_dma_done_irq(ep->indma);	ep->outirq = get_dma_done_irq(ep->outdma);	// allocate EP0's DMA done interrupts.	if (request_irq(ep->inirq, dma_done_intr, SA_INTERRUPT,			"USBdev ep0 IN", &usbserial)) {		err("Can't get ep0 IN dma done irq\n");		goto err_out;	}#if 0	if (request_irq(ep->outirq, dma_done_intr, SA_INTERRUPT,			"USBdev ep0 OUT", &usbserial)) {		err("Can't get ep0 OUT dma done irq\n");		goto err_out;	}#endif	/* initialize the devfs nodes for this device and let the user	   know what ports we are bound to */	for (i = 0; i < NUM_PORTS; ++i) {		tty_register_devfs(&serial_tty_driver, 0, i);		info("usbdev serial attached to ttyUSBdev%d (or devfs usb/ttsdev/%d)", 		     i, i);		port = &usbserial.port[i];		port->serial = &usbserial;		port->number = i;		port->send_complete_tq.routine = port_send_complete;		port->send_complete_tq.data = port;		port->receive_complete_tq.routine = port_receive_complete;		port->receive_complete_tq.data = port;		spin_lock_init(&port->port_lock);		// Initialize the port's bulk IN endpoint		ep = &port->ep_bulkin;		spin_lock_init(&ep->lock);		ep->desc = &ep_desc[NUM_PORTS * i];		ep->reg = &ep_reg[1 + NUM_PORTS * i];		ep->max_pkt_size = ep->desc->wMaxPacketSize;		ep->indma = ep->outdma = -1;		if ((ep->indma =		     request_au1000_dma(ep_dma_id[2+NUM_PORTS*i].id,				 ep_dma_id[2 + NUM_PORTS * i].str)) < 0) {			err("Can't get %s DMA\n",			    ep_dma_id[2 + NUM_PORTS * i].str);			goto err_out;		}		ep->inirq = get_dma_done_irq(ep->indma);		if (request_irq(ep->inirq, dma_done_intr, SA_INTERRUPT,				"USBdev bulk IN", &usbserial)) {			err("Can't get port %d bulk IN dma done irq\n", i);			goto err_out;		}		// Initialize the port's bulk OUT endpoint		ep = &port->ep_bulkout;		spin_lock_init(&ep->lock);		ep->desc = &ep_desc[NUM_PORTS * i + 1];		ep->reg = &ep_reg[1 + NUM_PORTS * i + 1];		ep->max_pkt_size = ep->desc->wMaxPacketSize;		ep->indma = ep->outdma = -1;		if ((ep->outdma =		     request_au1000_dma(ep_dma_id[2+NUM_PORTS*i + 1].id,					ep_dma_id[2+NUM_PORTS*i + 1].str)) < 0) {			err("Can't get %s DMA\n",			    ep_dma_id[2 + NUM_PORTS * i + 1].str);			goto err_out;		}		ep->outirq = get_dma_done_irq(ep->outdma);#if 0		if (request_irq(ep->outirq, dma_done_intr, SA_INTERRUPT,				"USBdev bulk OUT", &usbserial)) {			err("Can't get port %d bulk OUT dma done irq\n", i);			goto err_out;		}#endif	}	// enable device controller	outl_sync(0x0002, USB_DEV_ENABLE);	udelay(100);	outl_sync(0x0003, USB_DEV_ENABLE);	udelay(100);	for (i = 0; i < sizeof(au1000_config_table) / sizeof(u32); ++i)		outl_sync(au1000_config_table[i], USB_DEV_CONFIG);	// Flush the endpoint buffers and FIFOs	ep = &usbserial.ep_ctrl;	endpoint_flush(ep);	// start packet reception on control ep	kickstart_receive_packet(ep);	for (i = 0; i < NUM_PORTS; ++i) {		struct usb_serial_port *port = &usbserial.port[i];		endpoint_flush(&port->ep_bulkin);		endpoint_flush(&port->ep_bulkout);		// start packet reception on bulk OUT endpoint		kickstart_receive_packet(&port->ep_bulkout);	}	/*	 * Enable Receive FIFO Complete interrupts only. Transmit	 * complete is being handled by the DMA done interrupts.	 */	outl_sync(0x31, USB_DEV_INT_ENABLE);	return 0;      err_out:	usbdev_serial_exit();	return -1;}module_init(usbdev_serial_init);module_exit(usbdev_serial_exit);

⌨️ 快捷键说明

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