/**
 * adu_disconnect
 *
 * Called by the usb core when the device is removed from the system.
 */
static void adu_disconnect(struct usb_interface *interface)
{
	struct adu_device *dev;
	int minor;

	dbg(2," %s : enter", __func__);

	dev = usb_get_intfdata(interface);

	mutex_lock(&dev->mtx);	/* not interruptible */
	dev->udev = NULL;	/* poison */
	minor = dev->minor;
	usb_deregister_dev(interface, &adu_class);
	mutex_unlock(&dev->mtx);

	mutex_lock(&adutux_mutex);
	usb_set_intfdata(interface, NULL);

	/* if the device is not opened, then we clean up right now */
	dbg(2," %s : open count %d", __func__, dev->open_count);
	if (!dev->open_count)
		adu_delete(dev);

	mutex_unlock(&adutux_mutex);

	dev_info(&interface->dev, "ADU device adutux%d now disconnected\n",
		 (minor - ADU_MINOR_BASE));

	dbg(2," %s : leave", __func__);
}
Exemplo n.º 2
0
static int adu_release(struct inode *inode, struct file *file)
{
	struct adu_device *dev = NULL;
	int retval = 0;

	dbg(2," %s : enter", __FUNCTION__);

	if (file == NULL) {
 		dbg(1," %s : file is NULL", __FUNCTION__);
		retval = -ENODEV;
		goto exit;
	}

	dev = file->private_data;

	if (dev == NULL) {
 		dbg(1," %s : object is NULL", __FUNCTION__);
		retval = -ENODEV;
		goto exit;
	}

	/* lock our device */
	mutex_lock(&dev->mtx); /* not interruptible */

	if (dev->open_count <= 0) {
		dbg(1," %s : device not opened", __FUNCTION__);
		retval = -ENODEV;
		goto exit;
	}

	if (dev->udev == NULL) {
		/* the device was unplugged before the file was released */
		mutex_unlock(&dev->mtx);
		adu_delete(dev);
		dev = NULL;
	} else {
		/* do the work */
		retval = adu_release_internal(dev);
	}

exit:
	if (dev)
		mutex_unlock(&dev->mtx);
	dbg(2," %s : leave, return value %d", __FUNCTION__, retval);
	return retval;
}
static int adu_release(struct inode *inode, struct file *file)
{
	struct adu_device *dev;
	int retval = 0;

	dbg(2," %s : enter", __func__);

	if (file == NULL) {
 		dbg(1," %s : file is NULL", __func__);
		retval = -ENODEV;
		goto exit;
	}

	dev = file->private_data;
	if (dev == NULL) {
 		dbg(1," %s : object is NULL", __func__);
		retval = -ENODEV;
		goto exit;
	}

	mutex_lock(&adutux_mutex); /* not interruptible */

	if (dev->open_count <= 0) {
		dbg(1," %s : device not opened", __func__);
		retval = -ENODEV;
		goto unlock;
	}

	adu_release_internal(dev);
	if (dev->udev == NULL) {
		/* the device was unplugged before the file was released */
		if (!dev->open_count)	/* ... and we're the last user */
			adu_delete(dev);
	}
unlock:
	mutex_unlock(&adutux_mutex);
exit:
	dbg(2," %s : leave, return value %d", __func__, retval);
	return retval;
}
Exemplo n.º 4
0
static int adu_release(struct inode *inode, struct file *file)
{
	struct adu_device *dev;
	int retval = 0;

	dbg(2," %s : enter", __func__);

	if (file == NULL) {
 		dbg(1," %s : file is NULL", __func__);
		retval = -ENODEV;
		goto exit;
	}

	dev = file->private_data;
	if (dev == NULL) {
 		dbg(1," %s : object is NULL", __func__);
		retval = -ENODEV;
		goto exit;
	}

	mutex_lock(&adutux_mutex); 

	if (dev->open_count <= 0) {
		dbg(1," %s : device not opened", __func__);
		retval = -ENODEV;
		goto unlock;
	}

	adu_release_internal(dev);
	if (dev->udev == NULL) {
		
		if (!dev->open_count)	
			adu_delete(dev);
	}
unlock:
	mutex_unlock(&adutux_mutex);
exit:
	dbg(2," %s : leave, return value %d", __func__, retval);
	return retval;
}
Exemplo n.º 5
0
/**
 * adu_disconnect
 *
 * Called by the usb core when the device is removed from the system.
 */
static void adu_disconnect(struct usb_interface *interface)
{
	struct adu_device *dev;
	int minor;

	dbg(2," %s : enter", __FUNCTION__);

	mutex_lock(&disconnect_mutex); /* not interruptible */

	dev = usb_get_intfdata(interface);
	usb_set_intfdata(interface, NULL);

	down(&dev->sem); /* not interruptible */

	minor = dev->minor;

	/* give back our minor */
	usb_deregister_dev(interface, &adu_class);
	dev->minor = 0;

	/* if the device is not opened, then we clean up right now */
	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
	if (!dev->open_count) {
		up(&dev->sem);
		adu_delete(dev);
	} else {
		dev->udev = NULL;
		up(&dev->sem);
	}

	mutex_unlock(&disconnect_mutex);

	dev_info(&interface->dev, "ADU device adutux%d now disconnected",
		 (minor - ADU_MINOR_BASE));

	dbg(2," %s : leave", __FUNCTION__);
}
Exemplo n.º 6
0
static int adu_release_internal(struct adu_device *dev)
{
	int retval = 0;

	dbg(2," %s : enter", __FUNCTION__);

	if (dev->udev == NULL) {
		/* the device was unplugged before the file was released */
		adu_delete(dev);
		goto exit;
	}

	/* decrement our usage count for the device */
	--dev->open_count;
	dbg(2," %s : open count %d", __FUNCTION__, dev->open_count);
	if (dev->open_count <= 0) {
		adu_abort_transfers(dev);
		dev->open_count = 0;
	}

exit:
	dbg(2," %s : leave", __FUNCTION__);
	return retval;
}
/**
 * adu_probe
 *
 * Called by the usb core when a new device is connected that it thinks
 * this driver might be interested in.
 */
static int adu_probe(struct usb_interface *interface,
		     const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(interface);
	struct adu_device *dev = NULL;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	int retval = -ENODEV;
	int in_end_size;
	int out_end_size;
	int i;

	dbg(2," %s : enter", __func__);

	if (udev == NULL) {
		dev_err(&interface->dev, "udev is NULL.\n");
		goto exit;
	}

	/* allocate memory for our device state and initialize it */
	dev = kzalloc(sizeof(struct adu_device), GFP_KERNEL);
	if (dev == NULL) {
		dev_err(&interface->dev, "Out of memory\n");
		retval = -ENOMEM;
		goto exit;
	}

	mutex_init(&dev->mtx);
	spin_lock_init(&dev->buflock);
	dev->udev = udev;
	init_waitqueue_head(&dev->read_wait);
	init_waitqueue_head(&dev->write_wait);

	iface_desc = &interface->altsetting[0];

	/* set up the endpoint information */
	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
		endpoint = &iface_desc->endpoint[i].desc;

		if (usb_endpoint_is_int_in(endpoint))
			dev->interrupt_in_endpoint = endpoint;

		if (usb_endpoint_is_int_out(endpoint))
			dev->interrupt_out_endpoint = endpoint;
	}
	if (dev->interrupt_in_endpoint == NULL) {
		dev_err(&interface->dev, "interrupt in endpoint not found\n");
		goto error;
	}
	if (dev->interrupt_out_endpoint == NULL) {
		dev_err(&interface->dev, "interrupt out endpoint not found\n");
		goto error;
	}

	in_end_size = usb_endpoint_maxp(dev->interrupt_in_endpoint);
	out_end_size = usb_endpoint_maxp(dev->interrupt_out_endpoint);

	dev->read_buffer_primary = kmalloc((4 * in_end_size), GFP_KERNEL);
	if (!dev->read_buffer_primary) {
		dev_err(&interface->dev, "Couldn't allocate read_buffer_primary\n");
		retval = -ENOMEM;
		goto error;
	}

	/* debug code prime the buffer */
	memset(dev->read_buffer_primary, 'a', in_end_size);
	memset(dev->read_buffer_primary + in_end_size, 'b', in_end_size);
	memset(dev->read_buffer_primary + (2 * in_end_size), 'c', in_end_size);
	memset(dev->read_buffer_primary + (3 * in_end_size), 'd', in_end_size);

	dev->read_buffer_secondary = kmalloc((4 * in_end_size), GFP_KERNEL);
	if (!dev->read_buffer_secondary) {
		dev_err(&interface->dev, "Couldn't allocate read_buffer_secondary\n");
		retval = -ENOMEM;
		goto error;
	}

	/* debug code prime the buffer */
	memset(dev->read_buffer_secondary, 'e', in_end_size);
	memset(dev->read_buffer_secondary + in_end_size, 'f', in_end_size);
	memset(dev->read_buffer_secondary + (2 * in_end_size), 'g', in_end_size);
	memset(dev->read_buffer_secondary + (3 * in_end_size), 'h', in_end_size);

	dev->interrupt_in_buffer = kmalloc(in_end_size, GFP_KERNEL);
	if (!dev->interrupt_in_buffer) {
		dev_err(&interface->dev, "Couldn't allocate interrupt_in_buffer\n");
		goto error;
	}

	/* debug code prime the buffer */
	memset(dev->interrupt_in_buffer, 'i', in_end_size);

	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->interrupt_in_urb) {
		dev_err(&interface->dev, "Couldn't allocate interrupt_in_urb\n");
		goto error;
	}
	dev->interrupt_out_buffer = kmalloc(out_end_size, GFP_KERNEL);
	if (!dev->interrupt_out_buffer) {
		dev_err(&interface->dev, "Couldn't allocate interrupt_out_buffer\n");
		goto error;
	}
	dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->interrupt_out_urb) {
		dev_err(&interface->dev, "Couldn't allocate interrupt_out_urb\n");
		goto error;
	}

	if (!usb_string(udev, udev->descriptor.iSerialNumber, dev->serial_number,
			sizeof(dev->serial_number))) {
		dev_err(&interface->dev, "Could not retrieve serial number\n");
		goto error;
	}
	dbg(2," %s : serial_number=%s", __func__, dev->serial_number);

	/* we can register the device now, as it is ready */
	usb_set_intfdata(interface, dev);

	retval = usb_register_dev(interface, &adu_class);

	if (retval) {
		/* something prevented us from registering this driver */
		dev_err(&interface->dev, "Not able to get a minor for this device.\n");
		usb_set_intfdata(interface, NULL);
		goto error;
	}

	dev->minor = interface->minor;

	/* let the user know what node this device is now attached to */
	dev_info(&interface->dev, "ADU%d %s now attached to /dev/usb/adutux%d\n",
		 le16_to_cpu(udev->descriptor.idProduct), dev->serial_number,
		 (dev->minor - ADU_MINOR_BASE));
exit:
	dbg(2," %s : leave, return value %p (dev)", __func__, dev);

	return retval;

error:
	adu_delete(dev);
	return retval;
}