serial.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,079 行 · 第 1/4 页
C
2,079 行
* 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 semaphore *sem; port_num = tty->index; gs_debug("gs_open: (%d,%p,%p)\n", port_num, tty, file); tty->driver_data = NULL; 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; } sem = &gs_open_close_sem[port_num]; if (down_interruptible(sem)) { printk(KERN_ERR "gs_open: (%d,%p,%p) interrupted waiting for semaphore\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); spin_unlock_irqrestore(&dev->dev_lock, flags); up(sem); return -ENODEV; } 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); spin_unlock_irqrestore(&dev->dev_lock, flags); up(sem); return -ENODEV; } 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); spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return -EIO; } if (port->port_open_count > 0) { ++port->port_open_count; spin_unlock_irqrestore(&port->port_lock, flags); gs_debug("gs_open: (%d,%p,%p) already open\n", port_num, tty, file); up(sem); return 0; } /* 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; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return -EIO; } 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; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return -ENOMEM; } } /* 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; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return -EIO; } tty->driver_data = port; port->port_tty = tty; port->port_open_count = 1; port->port_in_use = 0; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); gs_debug("gs_open: (%d,%p,%p) completed\n", port_num, tty, file); return 0;}/* * gs_close */static void gs_close(struct tty_struct *tty, struct file *file){ unsigned long flags; struct gs_port *port = tty->driver_data; struct semaphore *sem; 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); sem = &gs_open_close_sem[port->port_num]; down(sem); spin_lock_irqsave(&port->port_lock, flags); if (port->port_open_count == 0) { printk(KERN_ERR "gs_close: (%d,%p,%p) port is already closed\n", port->port_num, tty, file); spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return; } if (port->port_open_count > 0) { --port->port_open_count; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return; } /* free disconnected port on final close */ if (port->port_dev == NULL) { kfree(port); spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return; } /* 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) { wait_cond_interruptible_timeout(port->port_write_wait, port->port_dev == NULL || gs_buf_data_avail(port->port_write_buf) == 0, &port->port_lock, flags, GS_CLOSE_TIMEOUT * HZ); } /* free disconnected port on final close */ /* (might have happened during the above sleep) */ if (port->port_dev == NULL) { kfree(port); spin_unlock_irqrestore(&port->port_lock, flags); up(sem); return; } gs_buf_clear(port->port_write_buf); tty->driver_data = NULL; port->port_tty = NULL; port->port_in_use = 0; spin_unlock_irqrestore(&port->port_lock, flags); up(sem); gs_debug("gs_close: (%d,%p,%p) completed\n", port->port_num, tty, file);}/* * gs_write */static int gs_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count){ unsigned long flags; struct gs_port *port = tty->driver_data; 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; /* copy from user into tmp buffer, get tmp_buf semaphore */ if (from_user) { if (count > GS_TMP_BUF_SIZE) count = GS_TMP_BUF_SIZE; down(&gs_tmp_buf_sem); if (copy_from_user(gs_tmp_buf, buf, count) != 0) { up(&gs_tmp_buf_sem); printk(KERN_ERR "gs_write: (%d,%p) cannot copy from user space\n", port->port_num, tty); return -EFAULT; } buf = gs_tmp_buf; } 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); spin_unlock_irqrestore(&port->port_lock, flags); if (from_user) up(&gs_tmp_buf_sem); return -EIO; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_write: (%d,%p) port is closed\n", port->port_num, tty); spin_unlock_irqrestore(&port->port_lock, flags); if (from_user) up(&gs_tmp_buf_sem); return -EBADF; } count = gs_buf_put(port->port_write_buf, buf, count); spin_unlock_irqrestore(&port->port_lock, flags); if (from_user) up(&gs_tmp_buf_sem); gs_send(gs_device); gs_debug("gs_write: (%d,%p) wrote %d bytes\n", port->port_num, tty, count); return count;}/* * 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, %p, %p\n", port->port_num, tty, ch, __builtin_return_address(0), __builtin_return_address(1), __builtin_return_address(2)); 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); spin_unlock_irqrestore(&port->port_lock, flags); return; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_put_char: (%d,%p) port is closed\n", port->port_num, tty); spin_unlock_irqrestore(&port->port_lock, flags); return; } gs_buf_put(port->port_write_buf, &ch, 1); 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); spin_unlock_irqrestore(&port->port_lock, flags); return; } if (port->port_open_count == 0) { printk(KERN_ERR "gs_flush_chars: (%d,%p) port is closed\n", port->port_num, tty); spin_unlock_irqrestore(&port->port_lock, flags); return; } spin_unlock_irqrestore(&port->port_lock, flags); gs_send(gs_device);}/* * 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 termios *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; if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { printk(KERN_ERR "gs_send: cannot queue read request, ret=%d\n",
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?