📄 aircable.c
字号:
if (num_bulk_out == 0) { dbg("Invalid interface, discarding"); return -ENODEV; } return 0;}static int aircable_attach (struct usb_serial *serial){ struct usb_serial_port *port = serial->port[0]; struct aircable_private *priv; priv = kzalloc(sizeof(struct aircable_private), GFP_KERNEL); if (!priv){ err("%s- kmalloc(%Zd) failed.", __FUNCTION__, sizeof(struct aircable_private)); return -ENOMEM; } /* Allocation of Circular Buffers */ priv->tx_buf = serial_buf_alloc(); if (priv->tx_buf == NULL) { kfree(priv); return -ENOMEM; } priv->rx_buf = serial_buf_alloc(); if (priv->rx_buf == NULL) { kfree(priv->tx_buf); kfree(priv); return -ENOMEM; } priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); priv->port = port; INIT_WORK(&priv->rx_work, aircable_read); usb_set_serial_port_data(serial->port[0], priv); return 0;}static void aircable_shutdown(struct usb_serial *serial){ struct usb_serial_port *port = serial->port[0]; struct aircable_private *priv = usb_get_serial_port_data(port); dbg("%s", __FUNCTION__); if (priv) { serial_buf_free(priv->tx_buf); serial_buf_free(priv->rx_buf); usb_set_serial_port_data(port, NULL); kfree(priv); }}static int aircable_write_room(struct usb_serial_port *port){ struct aircable_private *priv = usb_get_serial_port_data(port); return serial_buf_data_avail(priv->tx_buf);}static int aircable_write(struct usb_serial_port *port, const unsigned char *source, int count){ struct aircable_private *priv = usb_get_serial_port_data(port); int temp; dbg("%s - port %d, %d bytes", __FUNCTION__, port->number, count); usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, source); if (!count){ dbg("%s - write request of 0 bytes", __FUNCTION__); return count; } temp = serial_buf_put(priv->tx_buf, source, count); aircable_send(port); if (count > AIRCABLE_BUF_SIZE) count = AIRCABLE_BUF_SIZE; return count;}static void aircable_write_bulk_callback(struct urb *urb){ struct usb_serial_port *port = urb->context; int status = urb->status; int result; dbg("%s - urb status: %d", __FUNCTION__ , status); /* This has been taken from cypress_m8.c cypress_write_int_callback */ switch (status) { case 0: /* success */ break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ dbg("%s - urb shutting down with status: %d", __FUNCTION__, status); port->write_urb_busy = 0; return; default: /* error in the urb, so we have to resubmit it */ dbg("%s - Overflow in write", __FUNCTION__); dbg("%s - nonzero write bulk status received: %d", __FUNCTION__, status); port->write_urb->transfer_buffer_length = 1; port->write_urb->dev = port->serial->dev; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting write urb, error %d\n", __FUNCTION__, result); else return; } port->write_urb_busy = 0; aircable_send(port);}static void aircable_read_bulk_callback(struct urb *urb){ struct usb_serial_port *port = urb->context; struct aircable_private *priv = usb_get_serial_port_data(port); struct tty_struct *tty; unsigned long no_packages, remaining, package_length, i; int result, shift = 0; unsigned char *temp; int status = urb->status; dbg("%s - port %d", __FUNCTION__, port->number); if (status) { dbg("%s - urb status = %d", __FUNCTION__, status); if (!port->open_count) { dbg("%s - port is closed, exiting.", __FUNCTION__); return; } if (status == -EPROTO) { dbg("%s - caught -EPROTO, resubmitting the urb", __FUNCTION__); usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, aircable_read_bulk_callback, port); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); return; } dbg("%s - unable to handle the error, exiting.", __FUNCTION__); return; } usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length,urb->transfer_buffer); tty = port->tty; if (tty && urb->actual_length) { if (urb->actual_length <= 2) { /* This is an incomplete package */ serial_buf_put(priv->rx_buf, urb->transfer_buffer, urb->actual_length); } else { temp = urb->transfer_buffer; if (temp[0] == RX_HEADER_0) shift = HCI_HEADER_LENGTH; remaining = urb->actual_length; no_packages = urb->actual_length / (HCI_COMPLETE_FRAME); if (urb->actual_length % HCI_COMPLETE_FRAME != 0) no_packages+=1; for (i = 0; i < no_packages ;i++) { if (remaining > (HCI_COMPLETE_FRAME)) package_length = HCI_COMPLETE_FRAME; else package_length = remaining; remaining -= package_length; serial_buf_put(priv->rx_buf, urb->transfer_buffer + shift + (HCI_COMPLETE_FRAME) * (i), package_length - shift); } } aircable_read(&priv->rx_work); } /* Schedule the next read _if_ we are still open */ if (port->open_count) { usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), port->read_urb->transfer_buffer, port->read_urb->transfer_buffer_length, aircable_read_bulk_callback, port); result = usb_submit_urb(urb, GFP_ATOMIC); if (result) dev_err(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __FUNCTION__, result); } return;}/* Based on ftdi_sio.c throttle */static void aircable_throttle(struct usb_serial_port *port){ struct aircable_private *priv = usb_get_serial_port_data(port); unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->rx_lock, flags); priv->rx_flags |= THROTTLED; spin_unlock_irqrestore(&priv->rx_lock, flags);}/* Based on ftdi_sio.c unthrottle */static void aircable_unthrottle(struct usb_serial_port *port){ struct aircable_private *priv = usb_get_serial_port_data(port); int actually_throttled; unsigned long flags; dbg("%s - port %d", __FUNCTION__, port->number); spin_lock_irqsave(&priv->rx_lock, flags); actually_throttled = priv->rx_flags & ACTUALLY_THROTTLED; priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); spin_unlock_irqrestore(&priv->rx_lock, flags); if (actually_throttled) schedule_work(&priv->rx_work);}static struct usb_driver aircable_driver = { .name = "aircable", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, .no_dynamic_id = 1,};static struct usb_serial_driver aircable_device = { .driver = { .owner = THIS_MODULE, .name = "aircable", }, .usb_driver = &aircable_driver, .id_table = id_table, .num_ports = 1, .attach = aircable_attach, .probe = aircable_probe, .shutdown = aircable_shutdown, .write = aircable_write, .write_room = aircable_write_room, .write_bulk_callback = aircable_write_bulk_callback, .read_bulk_callback = aircable_read_bulk_callback, .throttle = aircable_throttle, .unthrottle = aircable_unthrottle,};static int __init aircable_init (void){ int retval; retval = usb_serial_register(&aircable_device); if (retval) goto failed_serial_register; retval = usb_register(&aircable_driver); if (retval) goto failed_usb_register; return 0;failed_serial_register: usb_serial_deregister(&aircable_device);failed_usb_register: return retval;}static void __exit aircable_exit (void){ usb_deregister(&aircable_driver); usb_serial_deregister(&aircable_device);}MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_VERSION(DRIVER_VERSION);MODULE_LICENSE("GPL");module_init(aircable_init);module_exit(aircable_exit);module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC(debug, "Debug enabled or not");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -