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

📄 usbatm.c

📁 LINUX 2.6.17.4的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
static int usbatm_atm_ioctl(struct atm_dev *atm_dev, unsigned int cmd,			  void __user * arg){	struct usbatm_data *instance = atm_dev->dev_data;	if (!instance || instance->disconnected) {		dbg("%s: %s!", __func__, instance ? "disconnected" : "NULL instance");		return -ENODEV;	}	switch (cmd) {	case ATM_QUERYLOOP:		return put_user(ATM_LM_NONE, (int __user *)arg) ? -EFAULT : 0;	default:		return -ENOIOCTLCMD;	}}static int usbatm_atm_init(struct usbatm_data *instance){	struct atm_dev *atm_dev;	int ret, i;	/* ATM init.  The ATM initialization scheme suffers from an intrinsic race	 * condition: callbacks we register can be executed at once, before we have	 * initialized the struct atm_dev.  To protect against this, all callbacks	 * abort if atm_dev->dev_data is NULL. */	atm_dev = atm_dev_register(instance->driver_name, &usbatm_atm_devops, -1, NULL);	if (!atm_dev) {		usb_err(instance, "%s: failed to register ATM device!\n", __func__);		return -1;	}	instance->atm_dev = atm_dev;	atm_dev->ci_range.vpi_bits = ATM_CI_MAX;	atm_dev->ci_range.vci_bits = ATM_CI_MAX;	atm_dev->signal = ATM_PHY_SIG_UNKNOWN;	/* temp init ATM device, set to 128kbit */	atm_dev->link_rate = 128 * 1000 / 424;	if (instance->driver->atm_start && ((ret = instance->driver->atm_start(instance, atm_dev)) < 0)) {		atm_err(instance, "%s: atm_start failed: %d!\n", __func__, ret);		goto fail;	}	usbatm_get_instance(instance);	/* dropped in usbatm_atm_dev_close */	/* ready for ATM callbacks */	mb();	atm_dev->dev_data = instance;	/* submit all rx URBs */	for (i = 0; i < num_rcv_urbs; i++)		usbatm_submit_urb(instance->urbs[i]);	return 0; fail:	instance->atm_dev = NULL;	atm_dev_deregister(atm_dev); /* usbatm_atm_dev_close will eventually be called */	return ret;}/************  USB  ************/static int usbatm_do_heavy_init(void *arg){	struct usbatm_data *instance = arg;	int ret;	daemonize(instance->driver->driver_name);	allow_signal(SIGTERM);	complete(&instance->thread_started);	ret = instance->driver->heavy_init(instance, instance->usb_intf);	if (!ret)		ret = usbatm_atm_init(instance);	mutex_lock(&instance->serialize);	instance->thread_pid = -1;	mutex_unlock(&instance->serialize);	complete_and_exit(&instance->thread_exited, ret);}static int usbatm_heavy_init(struct usbatm_data *instance){	int ret = kernel_thread(usbatm_do_heavy_init, instance, CLONE_KERNEL);	if (ret < 0) {		usb_err(instance, "%s: failed to create kernel_thread (%d)!\n", __func__, ret);		return ret;	}	mutex_lock(&instance->serialize);	instance->thread_pid = ret;	mutex_unlock(&instance->serialize);	wait_for_completion(&instance->thread_started);	return 0;}static void usbatm_tasklet_schedule(unsigned long data){	tasklet_schedule((struct tasklet_struct *) data);}static inline void usbatm_init_channel(struct usbatm_channel *channel){	spin_lock_init(&channel->lock);	INIT_LIST_HEAD(&channel->list);	channel->delay.function = usbatm_tasklet_schedule;	channel->delay.data = (unsigned long) &channel->tasklet;	init_timer(&channel->delay);}int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,		     struct usbatm_driver *driver){	struct device *dev = &intf->dev;	struct usb_device *usb_dev = interface_to_usbdev(intf);	struct usbatm_data *instance;	char *buf;	int error = -ENOMEM;	int i, length;	unsigned int maxpacket, num_packets;	dev_dbg(dev, "%s: trying driver %s with vendor=%04x, product=%04x, ifnum %2d\n",			__func__, driver->driver_name,			le16_to_cpu(usb_dev->descriptor.idVendor),			le16_to_cpu(usb_dev->descriptor.idProduct),			intf->altsetting->desc.bInterfaceNumber);	/* instance init */	instance = kzalloc(sizeof(*instance) + sizeof(struct urb *) * (num_rcv_urbs + num_snd_urbs), GFP_KERNEL);	if (!instance) {		dev_err(dev, "%s: no memory for instance data!\n", __func__);		return -ENOMEM;	}	/* public fields */	instance->driver = driver;	snprintf(instance->driver_name, sizeof(instance->driver_name), driver->driver_name);	instance->usb_dev = usb_dev;	instance->usb_intf = intf;	buf = instance->description;	length = sizeof(instance->description);	if ((i = usb_string(usb_dev, usb_dev->descriptor.iProduct, buf, length)) < 0)		goto bind;	buf += i;	length -= i;	i = scnprintf(buf, length, " (");	buf += i;	length -= i;	if (length <= 0 || (i = usb_make_path(usb_dev, buf, length)) < 0)		goto bind;	buf += i;	length -= i;	snprintf(buf, length, ")"); bind:	if (driver->bind && (error = driver->bind(instance, intf, id)) < 0) {			dev_err(dev, "%s: bind failed: %d!\n", __func__, error);			goto fail_free;	}	/* private fields */	kref_init(&instance->refcount);		/* dropped in usbatm_usb_disconnect */	mutex_init(&instance->serialize);	instance->thread_pid = -1;	init_completion(&instance->thread_started);	init_completion(&instance->thread_exited);	INIT_LIST_HEAD(&instance->vcc_list);	skb_queue_head_init(&instance->sndqueue);	usbatm_init_channel(&instance->rx_channel);	usbatm_init_channel(&instance->tx_channel);	tasklet_init(&instance->rx_channel.tasklet, usbatm_rx_process, (unsigned long)instance);	tasklet_init(&instance->tx_channel.tasklet, usbatm_tx_process, (unsigned long)instance);	instance->rx_channel.stride = ATM_CELL_SIZE + driver->rx_padding;	instance->tx_channel.stride = ATM_CELL_SIZE + driver->tx_padding;	instance->rx_channel.usbatm = instance->tx_channel.usbatm = instance;	if ((instance->flags & UDSL_USE_ISOC) && driver->isoc_in)		instance->rx_channel.endpoint = usb_rcvisocpipe(usb_dev, driver->isoc_in);	else		instance->rx_channel.endpoint = usb_rcvbulkpipe(usb_dev, driver->bulk_in);	instance->tx_channel.endpoint = usb_sndbulkpipe(usb_dev, driver->bulk_out);	/* tx buffer size must be a positive multiple of the stride */	instance->tx_channel.buf_size = max (instance->tx_channel.stride,			snd_buf_bytes - (snd_buf_bytes % instance->tx_channel.stride));	/* rx buffer size must be a positive multiple of the endpoint maxpacket */	maxpacket = usb_maxpacket(usb_dev, instance->rx_channel.endpoint, 0);	if ((maxpacket < 1) || (maxpacket > UDSL_MAX_BUF_SIZE)) {		dev_err(dev, "%s: invalid endpoint %02x!\n", __func__,				usb_pipeendpoint(instance->rx_channel.endpoint));		error = -EINVAL;		goto fail_unbind;	}	num_packets = max (1U, (rcv_buf_bytes + maxpacket / 2) / maxpacket); /* round */	if (num_packets * maxpacket > UDSL_MAX_BUF_SIZE)		num_packets--;	instance->rx_channel.buf_size = num_packets * maxpacket;	instance->rx_channel.packet_size = maxpacket;#ifdef DEBUG	for (i = 0; i < 2; i++) {		struct usbatm_channel *channel = i ?			&instance->tx_channel : &instance->rx_channel;		dev_dbg(dev, "%s: using %d byte buffer for %s channel 0x%p\n", __func__, channel->buf_size, i ? "tx" : "rx", channel);	}#endif	/* initialize urbs */	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {		u8 *buffer;		struct usbatm_channel *channel = i < num_rcv_urbs ?			&instance->rx_channel : &instance->tx_channel;		struct urb *urb;		unsigned int iso_packets = usb_pipeisoc(channel->endpoint) ? channel->buf_size / channel->packet_size : 0;		UDSL_ASSERT(!usb_pipeisoc(channel->endpoint) || usb_pipein(channel->endpoint));		urb = usb_alloc_urb(iso_packets, GFP_KERNEL);		if (!urb) {			dev_err(dev, "%s: no memory for urb %d!\n", __func__, i);			error = -ENOMEM;			goto fail_unbind;		}		instance->urbs[i] = urb;		/* zero the tx padding to avoid leaking information */		buffer = kzalloc(channel->buf_size, GFP_KERNEL);		if (!buffer) {			dev_err(dev, "%s: no memory for buffer %d!\n", __func__, i);			error = -ENOMEM;			goto fail_unbind;		}		usb_fill_bulk_urb(urb, instance->usb_dev, channel->endpoint,				  buffer, channel->buf_size, usbatm_complete, channel);		if (iso_packets) {			int j;			urb->interval = 1;			urb->transfer_flags = URB_ISO_ASAP;			urb->number_of_packets = iso_packets;			for (j = 0; j < iso_packets; j++) {				urb->iso_frame_desc[j].offset = channel->packet_size * j;				urb->iso_frame_desc[j].length = channel->packet_size;			}		}		/* put all tx URBs on the list of spares */		if (i >= num_rcv_urbs)			list_add_tail(&urb->urb_list, &channel->list);		vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p",		     __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);	}	instance->cached_vpi = ATM_VPI_UNSPEC;	instance->cached_vci = ATM_VCI_UNSPEC;	instance->cell_buf = kmalloc(instance->rx_channel.stride, GFP_KERNEL);	if (!instance->cell_buf) {		dev_err(dev, "%s: no memory for cell buffer!\n", __func__);		error = -ENOMEM;		goto fail_unbind;	}	if (!(instance->flags & UDSL_SKIP_HEAVY_INIT) && driver->heavy_init) {		error = usbatm_heavy_init(instance);	} else {		complete(&instance->thread_exited);	/* pretend that heavy_init was run */		error = usbatm_atm_init(instance);	}	if (error < 0)		goto fail_unbind;	usb_get_dev(usb_dev);	usb_set_intfdata(intf, instance);	return 0; fail_unbind:	if (instance->driver->unbind)		instance->driver->unbind(instance, intf); fail_free:	kfree(instance->cell_buf);	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {		if (instance->urbs[i])			kfree(instance->urbs[i]->transfer_buffer);		usb_free_urb(instance->urbs[i]);	}	kfree (instance);	return error;}EXPORT_SYMBOL_GPL(usbatm_usb_probe);void usbatm_usb_disconnect(struct usb_interface *intf){	struct device *dev = &intf->dev;	struct usbatm_data *instance = usb_get_intfdata(intf);	struct usbatm_vcc_data *vcc_data;	int i;	dev_dbg(dev, "%s entered\n", __func__);	if (!instance) {		dev_dbg(dev, "%s: NULL instance!\n", __func__);		return;	}	usb_set_intfdata(intf, NULL);	mutex_lock(&instance->serialize);	instance->disconnected = 1;	if (instance->thread_pid >= 0)		kill_proc(instance->thread_pid, SIGTERM, 1);	mutex_unlock(&instance->serialize);	wait_for_completion(&instance->thread_exited);	mutex_lock(&instance->serialize);	list_for_each_entry(vcc_data, &instance->vcc_list, list)		vcc_release_async(vcc_data->vcc, -EPIPE);	mutex_unlock(&instance->serialize);	tasklet_disable(&instance->rx_channel.tasklet);	tasklet_disable(&instance->tx_channel.tasklet);	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++)		usb_kill_urb(instance->urbs[i]);	del_timer_sync(&instance->rx_channel.delay);	del_timer_sync(&instance->tx_channel.delay);	/* turn usbatm_[rt]x_process into something close to a no-op */	/* no need to take the spinlock */	INIT_LIST_HEAD(&instance->rx_channel.list);	INIT_LIST_HEAD(&instance->tx_channel.list);	tasklet_enable(&instance->rx_channel.tasklet);	tasklet_enable(&instance->tx_channel.tasklet);	if (instance->atm_dev && instance->driver->atm_stop)		instance->driver->atm_stop(instance, instance->atm_dev);	if (instance->driver->unbind)		instance->driver->unbind(instance, intf);	instance->driver_data = NULL;	for (i = 0; i < num_rcv_urbs + num_snd_urbs; i++) {		kfree(instance->urbs[i]->transfer_buffer);		usb_free_urb(instance->urbs[i]);	}	kfree(instance->cell_buf);	/* ATM finalize */	if (instance->atm_dev)		atm_dev_deregister(instance->atm_dev);	usbatm_put_instance(instance);	/* taken in usbatm_usb_probe */}EXPORT_SYMBOL_GPL(usbatm_usb_disconnect);/*************  init  *************/static int __init usbatm_usb_init(void){	dbg("%s: driver version %s", __func__, DRIVER_VERSION);	if (sizeof(struct usbatm_control) > sizeof(((struct sk_buff *) 0)->cb)) {		printk(KERN_ERR "%s unusable with this kernel!\n", usbatm_driver_name);		return -EIO;	}	if ((num_rcv_urbs > UDSL_MAX_RCV_URBS)	    || (num_snd_urbs > UDSL_MAX_SND_URBS)	    || (rcv_buf_bytes < 1)	    || (rcv_buf_bytes > UDSL_MAX_BUF_SIZE)	    || (snd_buf_bytes < 1)	    || (snd_buf_bytes > UDSL_MAX_BUF_SIZE))		return -EINVAL;	return 0;}module_init(usbatm_usb_init);static void __exit usbatm_usb_exit(void){	dbg("%s", __func__);}module_exit(usbatm_usb_exit);MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");MODULE_VERSION(DRIVER_VERSION);/**************  debug  **************/#ifdef VERBOSE_DEBUGstatic int usbatm_print_packet(const unsigned char *data, int len){	unsigned char buffer[256];	int i = 0, j = 0;	for (i = 0; i < len;) {		buffer[0] = '\0';		sprintf(buffer, "%.3d :", i);		for (j = 0; (j < 16) && (i < len); j++, i++) {			sprintf(buffer, "%s %2.2x", buffer, data[i]);		}		dbg("%s", buffer);	}	return i;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -