📄 gserial.c
字号:
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 ) { spin_unlock(&port->port_lock ); return( 0 ); } size = gs_buf_get( port->port_write_buf, packet, size ); wake_up_interruptible( &port->port_tty->write_wait ); 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; /* 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_tty == NULL ) { printk( KERN_ERR "gs_recv_packet: port=%d, NULL tty pointer\n", port->port_num ); spin_unlock(&port->port_lock ); return( -EIO ); } if( port->port_tty->magic != TTY_MAGIC ) { printk( KERN_ERR "gs_recv_packet: port=%d, bad tty magic\n", port->port_num ); spin_unlock(&port->port_lock ); return( -EIO ); } 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 ); } spin_unlock(&port->port_lock ); return( 0 );}/** 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; usb_ep_autoconfig_reset(gadget); ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); if (!ep) goto autoconf_fail; EP_IN_NAME = ep->name; ep->driver_data = ep; /* claim the endpoint */ ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); if (!ep) goto autoconf_fail; EP_OUT_NAME = ep->name; ep->driver_data = ep; /* claim the endpoint */ /* device specific bcdDevice value in device descriptor */ if (gadget_is_net2280(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0001); } else if (gadget_is_pxa(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0002); } else if (gadget_is_sh(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0003); } else if (gadget_is_sa1100(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0004); } else if (gadget_is_goku(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0005); } else if (gadget_is_mq11xx(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0006); } else if (gadget_is_omap(gadget)) { gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0007); } else { printk(KERN_WARNING "gs_bind: controller '%s' not recognized\n", gadget->name); /* unrecognized, but safe unless bulk is REALLY quirky */ gs_device_desc.bcdDevice = __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); } gs_device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;#ifdef CONFIG_USB_GADGET_DUALSPEED /* assume ep0 uses the same packet size for both speeds */ gs_qualifier_desc.bMaxPacketSize0 = gs_device_desc.bMaxPacketSize0; /* assume endpoints are dual-speed */ gs_highspeed_in_desc.bEndpointAddress = gs_fullspeed_in_desc.bEndpointAddress; gs_highspeed_out_desc.bEndpointAddress = gs_fullspeed_out_desc.bEndpointAddress;#endif /* CONFIG_USB_GADGET_DUALSPEED */ usb_gadget_set_selfpowered(gadget); gs_device = dev = kmalloc(sizeof(struct gs_dev), GFP_KERNEL); if (dev == NULL) return -ENOMEM; snprintf (manufacturer, sizeof(manufacturer), UTS_SYSNAME " " UTS_RELEASE " with %s", gadget->name); memset(dev, 0, sizeof(struct gs_dev)); dev->dev_gadget = gadget; spin_lock_init(&dev->dev_lock); INIT_LIST_HEAD(&dev->dev_req_list); set_gadget_data(gadget, dev); if ((ret = gs_alloc_ports(dev, GFP_KERNEL)) != 0) { printk(KERN_ERR "gs_bind: cannot allocate ports\n"); gs_unbind(gadget); return ret; } /* preallocate control response and buffer */ dev->dev_ctrl_req = gs_alloc_req(gadget->ep0, GS_MAX_DESC_LEN, GFP_KERNEL); if (dev->dev_ctrl_req == NULL) { gs_unbind(gadget); return -ENOMEM; } dev->dev_ctrl_req->complete = gs_setup_complete; gadget->ep0->driver_data = dev; printk(KERN_INFO "gs_bind: %s %s bound\n", GS_LONG_NAME, GS_VERSION_STR); return 0;autoconf_fail: printk(KERN_ERR "gs_bind: cannot autoconfigure on %s\n", gadget->name); return -ENODEV;}/* * gs_unbind * * Called on module unload. Frees the control request and device * structure. */static void gs_unbind( struct usb_gadget *gadget ){ struct gs_dev *dev = get_gadget_data( gadget ); gs_device = NULL; /* read/write requests already freed, only control request remains */ if( dev != NULL ) { if( dev->dev_ctrl_req != NULL ) gs_free_req( gadget->ep0, dev->dev_ctrl_req ); gs_free_ports( dev ); kfree( dev ); set_gadget_data( gadget, NULL ); } printk( KERN_INFO "gs_unbind: %s %s unbound\n", GS_LONG_NAME, GS_VERSION_STR );}/* * gs_setup * * Implements all the control endpoint functionality that's not * handled in hardware or the hardware driver. * * Returns the size of the data sent to the host, or a negative * error number. */static int gs_setup( struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl ){ int ret = -EOPNOTSUPP; unsigned int sv_config; struct gs_dev *dev = get_gadget_data( gadget ); struct usb_request *req = dev->dev_ctrl_req; switch (ctrl->bRequest) { case USB_REQ_GET_DESCRIPTOR: if( ctrl->bRequestType != USB_DIR_IN ) break; switch (ctrl->wValue >> 8) { case USB_DT_DEVICE: ret = min( ctrl->wLength, (u16)sizeof(struct usb_device_descriptor) ); memcpy( req->buf, &gs_device_desc, ret ); break;#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: if (!gadget->is_dualspeed) break; ret = min( ctrl->wLength, (u16)sizeof(struct usb_qualifier_descriptor) ); memcpy( req->buf, &gs_qualifier_desc, ret ); break; case USB_DT_OTHER_SPEED_CONFIG:#endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: ret = gs_build_config_desc( req->buf, gadget->speed, ctrl->wValue >> 8, ctrl->wValue & 0xff ); if( ret >= 0 ) ret = min( ctrl->wLength, (u16)ret ); break; case USB_DT_STRING: /* wIndex == language code. */ ret = usb_gadget_get_string( &gs_string_table, ctrl->wValue & 0xff, req->buf ); if( ret >= 0 ) ret = min( ctrl->wLength, (u16)ret ); break; } break; case USB_REQ_SET_CONFIGURATION: if( ctrl->bRequestType != 0 ) break; spin_lock( &dev->dev_lock ); ret = gs_set_config( dev, ctrl->wValue ); spin_unlock( &dev->dev_lock ); break; case USB_REQ_GET_CONFIGURATION: if( ctrl->bRequestType != USB_DIR_IN ) break; *(u8 *)req->buf = dev->dev_config; ret = min( ctrl->wLength, (u16)1 ); break; case USB_REQ_SET_INTERFACE: if( ctrl->bRequestType != USB_RECIP_INTERFACE ) break; spin_lock( &dev->dev_lock ); if( dev->dev_config == GS_BULK_CONFIG_ID && ctrl->wIndex == GS_INTERFACE_ID && ctrl->wValue == GS_ALT_INTERFACE_ID ) { sv_config = dev->dev_config; /* since there is only one interface, setting the */ /* interface is equivalent to setting the config */ gs_reset_config( dev ); gs_set_config( dev, sv_config ); ret = 0; } spin_unlock( &dev->dev_lock ); break; case USB_REQ_GET_INTERFACE: if( ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE) ) break; if( dev->dev_config == GS_NO_CONFIG_ID ) break; if( ctrl->wIndex != GS_INTERFACE_ID ) { ret = -EDOM; break; } *(u8 *)req->buf = GS_ALT_INTERFACE_ID; ret = min( ctrl->wLength, (u16)1 ); break; default: printk( KERN_ERR "gs_setup: unknown request, type=%02x, request=%02x, value=%04x, index=%04x, length=%d\n", ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex, ctrl->wLength ); break; } /* respond with data transfer before status phase? */ if( ret >= 0 ) { req->length = ret; ret = usb_ep_queue( gadget->ep0, req, GFP_ATOMIC ); if( ret < 0 ) { printk( KERN_ERR "gs_setup: cannot queue response, ret=%d\n", ret ); req->status = 0; gs_setup_complete( gadget->ep0, req ); } } /* device either stalls (ret < 0) or reports success */ return( ret );}/* * gs_setup_complete */static void gs_setup_complete( struct usb_ep *ep, struct usb_request *req ){ if( req->status || req->actual != req->length ) { printk( KERN_ERR "gs_setup_complete: status error, status=%d, actual=%d, length=%d\n", req->status, req->actual, req->length ); }}/* * gs_disconnect * * Called when the device is disconnected. Frees the closed * ports and disconnects open ports. Open ports will be freed * on close. Then reallocates the ports for the next connection. */static void gs_disconnect( struct usb_gadget *gadget ){ unsigned long flags; struct gs_dev *dev = get_gadget_data( gadget ); spin_lock_irqsave( &dev->dev_lock, flags ); gs_reset_config( dev ); /* free closed ports and disconnect open ports */ /* (open ports will be freed when closed) */ gs_free_ports( dev ); /* re-allocate ports for the next connection */ if( gs_alloc_ports( dev, GFP_ATOMIC ) != 0 ) printk( KERN_ERR "gs_disconnect: cannot re-allocate ports\n" ); spin_unlock_irqrestore( &dev->dev_lock, flags ); printk( KERN_INFO "gs_disconnect: %s disconnected\n", GS_LONG_NAME );}/* * gs_set_config * * Configures the device by enabling device specific * optimizations, setting up the endpoints, allocating * read and write requests and queuing read requests. * * The device lock must be held when calling this function. */static int gs_set_config( struct gs_dev *dev, unsigned config ){ int i; int ret = 0; struct usb_gadget *gadget = dev->dev_gadget; struct usb_ep *ep; struct usb_request *req; struct gs_req_entry *req_entry; if( dev == NULL ) { printk( KERN_ERR "gs_set_config: NULL device pointer\n" );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -