⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aircable.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -