📄 serial.c
字号:
&gs_fullspeed_out_desc);
ret = usb_ep_enable(ep,ep_desc);
if (ret == 0) {
ep->driver_data = dev;
dev->dev_out_ep = ep;
dev->dev_out_ep_desc = ep_desc;
} else {
printk(KERN_ERR "gs_set_config: cannot enable out endpoint %s, ret=%d\n",
ep->name, ret);
goto exit_reset_config;
}
}
}
if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL
|| (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) {
printk(KERN_ERR "gs_set_config: cannot find endpoints\n");
ret = -ENODEV;
goto exit_reset_config;
}
/* allocate and queue read requests */
ep = dev->dev_out_ep;
for (i=0; i<read_q_size && ret == 0; i++) {
if ((req=gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC))) {
req->complete = gs_read_complete;
if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) {
printk(KERN_ERR "gs_set_config: cannot queue read request, ret=%d\n",
ret);
}
} else {
printk(KERN_ERR "gs_set_config: cannot allocate read requests\n");
ret = -ENOMEM;
goto exit_reset_config;
}
}
/* allocate write requests, and put on free list */
ep = dev->dev_in_ep;
for (i=0; i<write_q_size; i++) {
if ((req_entry=gs_alloc_req_entry(ep, ep->maxpacket, GFP_ATOMIC))) {
req_entry->re_req->complete = gs_write_complete;
list_add(&req_entry->re_entry, &dev->dev_req_list);
} else {
printk(KERN_ERR "gs_set_config: cannot allocate write requests\n");
ret = -ENOMEM;
goto exit_reset_config;
}
}
printk(KERN_INFO "gs_set_config: %s configured, %s speed %s config\n",
GS_LONG_NAME,
gadget->speed == USB_SPEED_HIGH ? "high" : "full",
config == GS_BULK_CONFIG_ID ? "BULK" : "CDC-ACM");
return 0;
exit_reset_config:
gs_reset_config(dev);
return ret;
}
/*
* gs_reset_config
*
* Mark the device as not configured, disable all endpoints,
* which forces completion of pending I/O and frees queued
* requests, and free the remaining write requests on the
* free list.
*
* The device lock must be held when calling this function.
*/
static void gs_reset_config(struct gs_dev *dev)
{
struct gs_req_entry *req_entry;
if (dev == NULL) {
printk(KERN_ERR "gs_reset_config: NULL device pointer\n");
return;
}
if (dev->dev_config == GS_NO_CONFIG_ID)
return;
dev->dev_config = GS_NO_CONFIG_ID;
/* free write requests on the free list */
while(!list_empty(&dev->dev_req_list)) {
req_entry = list_entry(dev->dev_req_list.next,
struct gs_req_entry, re_entry);
list_del(&req_entry->re_entry);
gs_free_req_entry(dev->dev_in_ep, req_entry);
}
/* disable endpoints, forcing completion of pending i/o; */
/* completion handlers free their requests in this case */
if (dev->dev_notify_ep) {
usb_ep_disable(dev->dev_notify_ep);
dev->dev_notify_ep = NULL;
}
if (dev->dev_in_ep) {
usb_ep_disable(dev->dev_in_ep);
dev->dev_in_ep = NULL;
}
if (dev->dev_out_ep) {
usb_ep_disable(dev->dev_out_ep);
dev->dev_out_ep = NULL;
}
}
/*
* gs_build_config_buf
*
* Builds the config descriptors in the given buffer and returns the
* length, or a negative error number.
*/
static int gs_build_config_buf(u8 *buf, enum usb_device_speed speed,
u8 type, unsigned int index, int is_otg)
{
int len;
int high_speed;
const struct usb_config_descriptor *config_desc;
const struct usb_descriptor_header **function;
if (index >= gs_device_desc.bNumConfigurations)
return -EINVAL;
/* other speed switches high and full speed */
high_speed = (speed == USB_SPEED_HIGH);
if (type == USB_DT_OTHER_SPEED_CONFIG)
high_speed = !high_speed;
if (use_acm) {
config_desc = &gs_acm_config_desc;
function = GS_SPEED_SELECT(high_speed,
gs_acm_highspeed_function,
gs_acm_fullspeed_function);
} else {
config_desc = &gs_bulk_config_desc;
function = GS_SPEED_SELECT(high_speed,
gs_bulk_highspeed_function,
gs_bulk_fullspeed_function);
}
/* for now, don't advertise srp-only devices */
if (!is_otg)
function++;
len = usb_gadget_config_buf(config_desc, buf, GS_MAX_DESC_LEN, function);
if (len < 0)
return len;
((struct usb_config_descriptor *)buf)->bDescriptorType = type;
return len;
}
/*
* gs_alloc_req
*
* Allocate a usb_request and its buffer. Returns a pointer to the
* usb_request or NULL if there is an error.
*/
static struct usb_request *
gs_alloc_req(struct usb_ep *ep, unsigned int len, unsigned kmalloc_flags)
{
struct usb_request *req;
if (ep == NULL)
return NULL;
req = usb_ep_alloc_request(ep, kmalloc_flags);
if (req != NULL) {
req->length = len;
req->buf = kmalloc(len, kmalloc_flags);
if (req->buf == NULL) {
usb_ep_free_request(ep, req);
return NULL;
}
}
return req;
}
/*
* gs_free_req
*
* Free a usb_request and its buffer.
*/
static void gs_free_req(struct usb_ep *ep, struct usb_request *req)
{
if (ep != NULL && req != NULL) {
kfree(req->buf);
usb_ep_free_request(ep, req);
}
}
/*
* gs_alloc_req_entry
*
* Allocates a request and its buffer, using the given
* endpoint, buffer len, and kmalloc flags.
*/
static struct gs_req_entry *
gs_alloc_req_entry(struct usb_ep *ep, unsigned len, unsigned kmalloc_flags)
{
struct gs_req_entry *req;
req = kmalloc(sizeof(struct gs_req_entry), kmalloc_flags);
if (req == NULL)
return NULL;
req->re_req = gs_alloc_req(ep, len, kmalloc_flags);
if (req->re_req == NULL) {
kfree(req);
return NULL;
}
req->re_req->context = req;
return req;
}
/*
* gs_free_req_entry
*
* Frees a request and its buffer.
*/
static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req)
{
if (ep != NULL && req != NULL) {
if (req->re_req != NULL)
gs_free_req(ep, req->re_req);
kfree(req);
}
}
/*
* gs_alloc_ports
*
* Allocate all ports and set the gs_dev struct to point to them.
* Return 0 if successful, or a negative error number.
*
* The device lock is normally held when calling this function.
*/
static int gs_alloc_ports(struct gs_dev *dev, unsigned kmalloc_flags)
{
int i;
struct gs_port *port;
if (dev == NULL)
return -EIO;
for (i=0; i<GS_NUM_PORTS; i++) {
if ((port=(struct gs_port *)kmalloc(sizeof(struct gs_port), kmalloc_flags)) == NULL)
return -ENOMEM;
memset(port, 0, sizeof(struct gs_port));
port->port_dev = dev;
port->port_num = i;
port->port_line_coding.dwDTERate = cpu_to_le32(GS_DEFAULT_DTE_RATE);
port->port_line_coding.bCharFormat = GS_DEFAULT_CHAR_FORMAT;
port->port_line_coding.bParityType = GS_DEFAULT_PARITY;
port->port_line_coding.bDataBits = GS_DEFAULT_DATA_BITS;
spin_lock_init(&port->port_lock);
init_waitqueue_head(&port->port_write_wait);
dev->dev_port[i] = port;
}
return 0;
}
/*
* gs_free_ports
*
* Free all closed ports. Open ports are disconnected by
* freeing their write buffers, setting their device pointers
* and the pointers to them in the device to NULL. These
* ports will be freed when closed.
*
* The device lock is normally held when calling this function.
*/
static void gs_free_ports(struct gs_dev *dev)
{
int i;
unsigned long flags;
struct gs_port *port;
if (dev == NULL)
return;
for (i=0; i<GS_NUM_PORTS; i++) {
if ((port=dev->dev_port[i]) != NULL) {
dev->dev_port[i] = NULL;
spin_lock_irqsave(&port->port_lock, flags);
if (port->port_write_buf != NULL) {
gs_buf_free(port->port_write_buf);
port->port_write_buf = NULL;
}
if (port->port_open_count > 0 || port->port_in_use) {
port->port_dev = NULL;
wake_up_interruptible(&port->port_write_wait);
if (port->port_tty) {
wake_up_interruptible(&port->port_tty->read_wait);
wake_up_interruptible(&port->port_tty->write_wait);
}
spin_unlock_irqrestore(&port->port_lock, flags);
} else {
spin_unlock_irqrestore(&port->port_lock, flags);
kfree(port);
}
}
}
}
/* Circular Buffer */
/*
* gs_buf_alloc
*
* Allocate a circular buffer and all associated memory.
*/
static struct gs_buf *gs_buf_alloc(unsigned int size, unsigned kmalloc_flags)
{
struct gs_buf *gb;
if (size == 0)
return NULL;
gb = (struct gs_buf *)kmalloc(sizeof(struct gs_buf), kmalloc_flags);
if (gb == NULL)
return NULL;
gb->buf_buf = kmalloc(size, kmalloc_flags);
if (gb->buf_buf == NULL) {
kfree(gb);
return NULL;
}
gb->buf_size = size;
gb->buf_get = gb->buf_put = gb->buf_buf;
return gb;
}
/*
* gs_buf_free
*
* Free the buffer and all associated memory.
*/
void gs_buf_free(struct gs_buf *gb)
{
if (gb) {
kfree(gb->buf_buf);
kfree(gb);
}
}
/*
* gs_buf_clear
*
* Clear out all data in the circular buffer.
*/
void gs_buf_clear(struct gs_buf *gb)
{
if (gb != NULL)
gb->buf_get = gb->buf_put;
/* equivalent to a get of all data available */
}
/*
* gs_buf_data_avail
*
* Return the number of bytes of data available in the circular
* buffer.
*/
unsigned int gs_buf_data_avail(struct gs_buf *gb)
{
if (gb != NULL)
return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size;
else
return 0;
}
/*
* gs_buf_space_avail
*
* Return the number of bytes of space available in the circular
* buffer.
*/
unsigned int gs_buf_space_avail(struct gs_buf *gb)
{
if (gb != NULL)
return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size;
else
return 0;
}
/*
* gs_buf_put
*
* Copy data data from a user buffer and put it into the circular buffer.
* Restrict to the amount of space available.
*
* Return the number of bytes copied.
*/
unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, unsigned int count)
{
unsigned int len;
if (gb == NULL)
return 0;
len = gs_buf_space_avail(gb);
if (count > len)
count = len;
if (count == 0)
return 0;
len = gb->buf_buf + gb->buf_size - gb->buf_put;
if (count > len) {
memcpy(gb->buf_put, buf, len);
memcpy(gb->buf_buf, buf+len, count - len);
gb->buf_put = gb->buf_buf + count - len;
} else {
memcpy(gb->buf_put, buf, count);
if (count < len)
gb->buf_put += count;
else /* count == len */
gb->buf_put = gb->buf_buf;
}
return count;
}
/*
* gs_buf_get
*
* Get data from the circular buffer and copy to the given buffer.
* Restrict to the amount of data available.
*
* Return the number of bytes copied.
*/
unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count)
{
unsigned int len;
if (gb == NULL)
return 0;
len = gs_buf_data_avail(gb);
if (count > len)
count = len;
if (count == 0)
return 0;
len = gb->buf_buf + gb->buf_size - gb->buf_get;
if (count > len) {
memcpy(buf, gb->buf_get, len);
memcpy(buf+len, gb->buf_buf, count - len);
gb->buf_get = gb->buf_buf + count - len;
} else {
memcpy(buf, gb->buf_get, count);
if (count < len)
gb->buf_get += count;
else /* count == len */
gb->buf_get = gb->buf_buf;
}
return count;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -