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

📄 serial.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
	printk(KERN_INFO "gs_module_init: %s %s loaded\n", GS_LONG_NAME, GS_VERSION_STR);	return 0;}/** gs_module_exit** Unregister as a tty driver and a USB gadget driver.*/static void __exit gs_module_exit(void){	tty_unregister_driver(gs_tty_driver);	put_tty_driver(gs_tty_driver);	usb_gadget_unregister_driver(&gs_gadget_driver);	printk(KERN_INFO "gs_module_exit: %s %s unloaded\n", GS_LONG_NAME, GS_VERSION_STR);}/* TTY Driver *//* * gs_open */static int gs_open(struct tty_struct *tty, struct file *file){	int port_num;	unsigned long flags;	struct gs_port *port;	struct gs_dev *dev;	struct gs_buf *buf;	struct mutex *mtx;	int ret;	port_num = tty->index;	gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file);	if (port_num < 0 || port_num >= GS_NUM_PORTS) {		printk(KERN_ERR "gs_open: (%d,%p,%p) invalid port number\n",			port_num, tty, file);		return -ENODEV;	}	dev = gs_device;	if (dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL device pointer\n",			port_num, tty, file);		return -ENODEV;	}	mtx = &gs_open_close_lock[port_num];	if (mutex_lock_interruptible(mtx)) {		printk(KERN_ERR		"gs_open: (%d,%p,%p) interrupted waiting for mutex\n",			port_num, tty, file);		return -ERESTARTSYS;	}	spin_lock_irqsave(&dev->dev_lock, flags);	if (dev->dev_config == GS_NO_CONFIG_ID) {		printk(KERN_ERR			"gs_open: (%d,%p,%p) device is not connected\n",			port_num, tty, file);		ret = -ENODEV;		goto exit_unlock_dev;	}	port = dev->dev_port[port_num];	if (port == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) NULL port pointer\n",			port_num, tty, file);		ret = -ENODEV;		goto exit_unlock_dev;	}	spin_lock(&port->port_lock);	spin_unlock(&dev->dev_lock);	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (1)\n",			port_num, tty, file);		ret = -EIO;		goto exit_unlock_port;	}	if (port->port_open_count > 0) {		++port->port_open_count;		gs_debug("gs_open: (%d,%p,%p) already open\n",			port_num, tty, file);		ret = 0;		goto exit_unlock_port;	}	tty->driver_data = NULL;	/* mark port as in use, we can drop port lock and sleep if necessary */	port->port_in_use = 1;	/* allocate write buffer on first open */	if (port->port_write_buf == NULL) {		spin_unlock_irqrestore(&port->port_lock, flags);		buf = gs_buf_alloc(write_buf_size, GFP_KERNEL);		spin_lock_irqsave(&port->port_lock, flags);		/* might have been disconnected while asleep, check */		if (port->port_dev == NULL) {			printk(KERN_ERR				"gs_open: (%d,%p,%p) port disconnected (2)\n",				port_num, tty, file);			port->port_in_use = 0;			ret = -EIO;			goto exit_unlock_port;		}		if ((port->port_write_buf=buf) == NULL) {			printk(KERN_ERR "gs_open: (%d,%p,%p) cannot allocate port write buffer\n",				port_num, tty, file);			port->port_in_use = 0;			ret = -ENOMEM;			goto exit_unlock_port;		}	}	/* wait for carrier detect (not implemented) */	/* might have been disconnected while asleep, check */	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_open: (%d,%p,%p) port disconnected (3)\n",			port_num, tty, file);		port->port_in_use = 0;		ret = -EIO;		goto exit_unlock_port;	}	tty->driver_data = port;	port->port_tty = tty;	port->port_open_count = 1;	port->port_in_use = 0;	gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file);	ret = 0;exit_unlock_port:	spin_unlock_irqrestore(&port->port_lock, flags);	mutex_unlock(mtx);	return ret;exit_unlock_dev:	spin_unlock_irqrestore(&dev->dev_lock, flags);	mutex_unlock(mtx);	return ret;}/* * gs_close */#define GS_WRITE_FINISHED_EVENT_SAFELY(p)			\({								\	int cond;						\								\	spin_lock_irq(&(p)->port_lock);				\	cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \	spin_unlock_irq(&(p)->port_lock);			\	cond;							\})static void gs_close(struct tty_struct *tty, struct file *file){	struct gs_port *port = tty->driver_data;	struct mutex *mtx;	if (port == NULL) {		printk(KERN_ERR "gs_close: NULL port pointer\n");		return;	}	gs_debug("gs_close: (%d,%p,%p)\n", port->port_num, tty, file);	mtx = &gs_open_close_lock[port->port_num];	mutex_lock(mtx);	spin_lock_irq(&port->port_lock);	if (port->port_open_count == 0) {		printk(KERN_ERR			"gs_close: (%d,%p,%p) port is already closed\n",			port->port_num, tty, file);		goto exit;	}	if (port->port_open_count > 1) {		--port->port_open_count;		goto exit;	}	/* free disconnected port on final close */	if (port->port_dev == NULL) {		kfree(port);		goto exit;	}	/* mark port as closed but in use, we can drop port lock */	/* and sleep if necessary */	port->port_in_use = 1;	port->port_open_count = 0;	/* wait for write buffer to drain, or */	/* at most GS_CLOSE_TIMEOUT seconds */	if (gs_buf_data_avail(port->port_write_buf) > 0) {		spin_unlock_irq(&port->port_lock);		wait_event_interruptible_timeout(port->port_write_wait,					GS_WRITE_FINISHED_EVENT_SAFELY(port),					GS_CLOSE_TIMEOUT * HZ);		spin_lock_irq(&port->port_lock);	}	/* free disconnected port on final close */	/* (might have happened during the above sleep) */	if (port->port_dev == NULL) {		kfree(port);		goto exit;	}	gs_buf_clear(port->port_write_buf);	tty->driver_data = NULL;	port->port_tty = NULL;	port->port_in_use = 0;	gs_debug("gs_close: (%d,%p,%p) completed\n",		port->port_num, tty, file);exit:	spin_unlock_irq(&port->port_lock);	mutex_unlock(mtx);}/* * gs_write */static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count){	unsigned long flags;	struct gs_port *port = tty->driver_data;	int ret;	if (port == NULL) {		printk(KERN_ERR "gs_write: NULL port pointer\n");		return -EIO;	}	gs_debug("gs_write: (%d,%p) writing %d bytes\n", port->port_num, tty,		count);	if (count == 0)		return 0;	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_write: (%d,%p) port is not connected\n",			port->port_num, tty);		ret = -EIO;		goto exit;	}	if (port->port_open_count == 0) {		printk(KERN_ERR "gs_write: (%d,%p) port is closed\n",			port->port_num, tty);		ret = -EBADF;		goto exit;	}	count = gs_buf_put(port->port_write_buf, buf, count);	spin_unlock_irqrestore(&port->port_lock, flags);	gs_send(gs_device);	gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty,		count);	return count;exit:	spin_unlock_irqrestore(&port->port_lock, flags);	return ret;}/* * gs_put_char */static void gs_put_char(struct tty_struct *tty, unsigned char ch){	unsigned long flags;	struct gs_port *port = tty->driver_data;	if (port == NULL) {		printk(KERN_ERR "gs_put_char: NULL port pointer\n");		return;	}	gs_debug("gs_put_char: (%d,%p) char=0x%x, called from %p\n",		port->port_num, tty, ch, __builtin_return_address(0));	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_dev == NULL) {		printk(KERN_ERR "gs_put_char: (%d,%p) port is not connected\n",			port->port_num, tty);		goto exit;	}	if (port->port_open_count == 0) {		printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n",			port->port_num, tty);		goto exit;	}	gs_buf_put(port->port_write_buf, &ch, 1);exit:	spin_unlock_irqrestore(&port->port_lock, flags);}/* * gs_flush_chars */static void gs_flush_chars(struct tty_struct *tty){	unsigned long flags;	struct gs_port *port = tty->driver_data;	if (port == NULL) {		printk(KERN_ERR "gs_flush_chars: NULL port pointer\n");		return;	}	gs_debug("gs_flush_chars: (%d,%p)\n", port->port_num, tty);	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_dev == NULL) {		printk(KERN_ERR			"gs_flush_chars: (%d,%p) port is not connected\n",			port->port_num, tty);		goto exit;	}	if (port->port_open_count == 0) {		printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n",			port->port_num, tty);		goto exit;	}	spin_unlock_irqrestore(&port->port_lock, flags);	gs_send(gs_device);	return;exit:	spin_unlock_irqrestore(&port->port_lock, flags);}/* * gs_write_room */static int gs_write_room(struct tty_struct *tty){	int room = 0;	unsigned long flags;	struct gs_port *port = tty->driver_data;	if (port == NULL)		return 0;	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_dev != NULL && port->port_open_count > 0	&& port->port_write_buf != NULL)		room = gs_buf_space_avail(port->port_write_buf);	spin_unlock_irqrestore(&port->port_lock, flags);	gs_debug("gs_write_room: (%d,%p) room=%d\n",		port->port_num, tty, room);	return room;}/* * gs_chars_in_buffer */static int gs_chars_in_buffer(struct tty_struct *tty){	int chars = 0;	unsigned long flags;	struct gs_port *port = tty->driver_data;	if (port == NULL)		return 0;	spin_lock_irqsave(&port->port_lock, flags);	if (port->port_dev != NULL && port->port_open_count > 0	&& port->port_write_buf != NULL)		chars = gs_buf_data_avail(port->port_write_buf);	spin_unlock_irqrestore(&port->port_lock, flags);	gs_debug("gs_chars_in_buffer: (%d,%p) chars=%d\n",		port->port_num, tty, chars);	return chars;}/* * gs_throttle */static void gs_throttle(struct tty_struct *tty){}/* * gs_unthrottle */static void gs_unthrottle(struct tty_struct *tty){}/* * gs_break */static void gs_break(struct tty_struct *tty, int break_state){}/* * gs_ioctl */static int gs_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg){	struct gs_port *port = tty->driver_data;	if (port == NULL) {		printk(KERN_ERR "gs_ioctl: NULL port pointer\n");		return -EIO;	}	gs_debug("gs_ioctl: (%d,%p,%p) cmd=0x%4.4x, arg=%lu\n",		port->port_num, tty, file, cmd, arg);	/* handle ioctls */	/* could not handle ioctl */	return -ENOIOCTLCMD;}/* * gs_set_termios */static void gs_set_termios(struct tty_struct *tty, struct ktermios *old){}/** gs_send** This function finds available write requests, calls* gs_send_packet to fill these packets with data, and* continues until either there are no more write requests* available or no more data to send.  This function is* run whenever data arrives or write requests are available.*/static int gs_send(struct gs_dev *dev){	int ret,len;	unsigned long flags;	struct usb_ep *ep;	struct usb_request *req;	struct gs_req_entry *req_entry;	if (dev == NULL) {		printk(KERN_ERR "gs_send: NULL device pointer\n");		return -ENODEV;	}	spin_lock_irqsave(&dev->dev_lock, flags);	ep = dev->dev_in_ep;	while(!list_empty(&dev->dev_req_list)) {		req_entry = list_entry(dev->dev_req_list.next,			struct gs_req_entry, re_entry);		req = req_entry->re_req;		len = gs_send_packet(dev, req->buf, ep->maxpacket);		if (len > 0) {			gs_debug_level(3, "gs_send: len=%d, 0x%2.2x "					"0x%2.2x 0x%2.2x ...\n", len,					*((unsigned char *)req->buf),					*((unsigned char *)req->buf+1),					*((unsigned char *)req->buf+2));			list_del(&req_entry->re_entry);			req->length = len;			spin_unlock_irqrestore(&dev->dev_lock, flags);			if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {				printk(KERN_ERR				"gs_send: cannot queue read request, ret=%d\n",					ret);				spin_lock_irqsave(&dev->dev_lock, flags);				break;			}			spin_lock_irqsave(&dev->dev_lock, flags);		} else {			break;		}	}	spin_unlock_irqrestore(&dev->dev_lock, flags);	return 0;}/* * gs_send_packet * * If there is data to send, a packet is built in the given * buffer and the size is returned.  If there is no data to * send, 0 is returned.  If there is any error a negative * error number is returned. * * Called during USB completion routine, on interrupt time. * * We assume that disconnect will not happen until all completion * routines have completed, so we can assume that the dev_port * array does not change during the lifetime of this function. */static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size){	unsigned int len;	struct gs_port *port;	/* TEMPORARY -- only port 0 is supported right now */	port = dev->dev_port[0];	if (port == NULL) {		printk(KERN_ERR			"gs_send_packet: port=%d, NULL port pointer\n",			0);		return -EIO;	}	spin_lock(&port->port_lock);	len = gs_buf_data_avail(port->port_write_buf);	if (len < size)		size = len;	if (size == 0)		goto exit;	size = gs_buf_get(port->port_write_buf, packet, size);	if (port->port_tty)		wake_up_interruptible(&port->port_tty->write_wait);exit:	spin_unlock(&port->port_lock);

⌨️ 快捷键说明

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