📄 serial.c
字号:
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, %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); 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 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", ret); break; } } 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); return size;}/* * gs_recv_packet * * Called for each USB packet received. Reads the packet * header and stuffs the data in the appropriate tty buffer. * Returns 0 if successful, or a negative error number. * * 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_recv_packet(struct gs_dev *dev, char *packet, unsigned int size){ unsigned int len; struct gs_port *port; int ret; /* TEMPORARY -- only port 0 is supported right now */ port = dev->dev_port[0]; if (port == NULL) { printk(KERN_ERR "gs_recv_packet: port=%d, NULL port pointer\n", port->port_num); return -EIO; } spin_lock(&port->port_lock); if (port->port_open_count == 0) { printk(KERN_ERR "gs_recv_packet: port=%d, port is closed\n", port->port_num); ret = -EIO; goto exit; } if (port->port_tty == NULL) { printk(KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n", port->port_num); ret = -EIO; goto exit; } if (port->port_tty->magic != TTY_MAGIC) { printk(KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n", port->port_num); ret = -EIO; goto exit; } len = (unsigned int)(TTY_FLIPBUF_SIZE - port->port_tty->flip.count); if (len < size) size = len; if (size > 0) { memcpy(port->port_tty->flip.char_buf_ptr, packet, size); port->port_tty->flip.char_buf_ptr += size; port->port_tty->flip.count += size; tty_flip_buffer_push(port->port_tty); wake_up_interruptible(&port->port_tty->read_wait); } ret = 0;exit: spin_unlock(&port->port_lock); return ret;}/** gs_read_complete*/static void gs_read_complete(struct usb_ep *ep, struct usb_request *req){ int ret; struct gs_dev *dev = ep->driver_data; if (dev == NULL) { printk(KERN_ERR "gs_read_complete: NULL device pointer\n"); return; } switch(req->status) { case 0: /* normal completion */ gs_recv_packet(dev, req->buf, req->actual);requeue: req->length = ep->maxpacket; if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { printk(KERN_ERR "gs_read_complete: cannot queue read request, ret=%d\n", ret); } break; case -ESHUTDOWN: /* disconnect */ gs_debug("gs_read_complete: shutdown\n"); gs_free_req(ep, req); break; default: /* unexpected */ printk(KERN_ERR "gs_read_complete: unexpected status error, status=%d\n", req->status); goto requeue; break; }}/** gs_write_complete*/static void gs_write_complete(struct usb_ep *ep, struct usb_request *req){ struct gs_dev *dev = ep->driver_data; struct gs_req_entry *gs_req = req->context; if (dev == NULL) { printk(KERN_ERR "gs_write_complete: NULL device pointer\n"); return; } switch(req->status) { case 0: /* normal completion */requeue: if (gs_req == NULL) { printk(KERN_ERR "gs_write_complete: NULL request pointer\n"); return; } spin_lock(&dev->dev_lock); list_add(&gs_req->re_entry, &dev->dev_req_list); spin_unlock(&dev->dev_lock); gs_send(dev); break; case -ESHUTDOWN: /* disconnect */ gs_debug("gs_write_complete: shutdown\n"); gs_free_req(ep, req); break; default: printk(KERN_ERR "gs_write_complete: unexpected status error, status=%d\n", req->status); goto requeue; break; }}/* Gadget Driver *//* * gs_bind * * Called on module load. Allocates and initializes the device * structure and a control request. */static int gs_bind(struct usb_gadget *gadget){ int ret; struct usb_ep *ep; struct gs_dev *dev;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -