示例#1
0
/**
 *	usb_tranzport_disconnect
 *
 *	Called by the usb core when the device is removed from the system.
 */
static void usb_tranzport_disconnect(struct usb_interface *intf)
{
	struct usb_tranzport *dev;
	int minor;
	mutex_lock(&disconnect_mutex);
	dev = usb_get_intfdata(intf);
	usb_set_intfdata(intf, NULL);
	down(&dev->sem);
	minor = intf->minor;
	/* give back our minor */
	usb_deregister_dev(intf, &usb_tranzport_class);

	/* if the device is not opened, then we clean up right now */
	if (!dev->open_count) {
		up(&dev->sem);
		usb_tranzport_delete(dev);
	} else {
		dev->intf = NULL;
		up(&dev->sem);
	}

	mutex_unlock(&disconnect_mutex);

	dev_info(&intf->dev, "Tranzport Surface #%d now disconnected\n",
		 (minor - USB_TRANZPORT_MINOR_BASE));
}
/**
 *	usb_tranzport_release
 */
static int usb_tranzport_release(struct inode *inode, struct file *file)
{
	struct usb_tranzport *dev;
	int retval = 0;

	dev = file->private_data;

	if (dev == NULL) {
		retval = -ENODEV;
		goto exit;
	}

	if (mutex_lock_interruptible(&dev->mtx)) {
		retval = -ERESTARTSYS;
		goto exit;
	}

	if (dev->open_count != 1) {
		retval = -ENODEV;
		goto unlock_exit;
	}

	if (dev->intf == NULL) {
		/* the device was unplugged before the file was released */
		mutex_unlock(&dev->mtx);
		/* unlock here as usb_tranzport_delete frees dev */
		usb_tranzport_delete(dev);
		retval = -ENODEV;
		goto exit;
	}

	/* wait until write transfer is finished */
	if (dev->interrupt_out_busy)
		wait_event_interruptible_timeout(dev->write_wait,
						!dev->interrupt_out_busy,
						2 * HZ);
	usb_tranzport_abort_transfers(dev);
	dev->open_count = 0;

unlock_exit:
	mutex_unlock(&dev->mtx);

exit:
	return retval;
}
示例#3
0
/**
 *	usb_tranzport_probe
 *
 *	Called by the usb core when a new device is connected that it thinks
 *	this driver might be interested in.
 */
static int usb_tranzport_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
	struct usb_device *udev = interface_to_usbdev(intf);
	struct usb_tranzport *dev = NULL;
	struct usb_host_interface *iface_desc;
	struct usb_endpoint_descriptor *endpoint;
	int i;
	int true_size;
	int retval = -ENOMEM;

	/* allocate memory for our device state and intialize it */

	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
	if (dev == NULL) {
		dev_err(&intf->dev, "Out of memory\n");
		goto exit;
	}
	init_MUTEX(&dev->sem);
	dev->intf = intf;
	init_waitqueue_head(&dev->read_wait);
	init_waitqueue_head(&dev->write_wait);

	iface_desc = intf->cur_altsetting;

	/* 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(&intf->dev, "Interrupt in endpoint not found\n");
		goto error;
	}
	if (dev->interrupt_out_endpoint == NULL)
		dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");


	dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);

	if (dev->interrupt_in_endpoint_size != 8)
	    dev_warn(&intf->dev, "Interrupt in endpoint size is not 8!\n");

	if(ring_buffer_size == 0) { ring_buffer_size = RING_BUFFER_SIZE; }
	true_size = min(ring_buffer_size,RING_BUFFER_SIZE);
	/* FIXME - there are more usb_alloc routines for dma correctness. Needed? */

	dev->ring_buffer = kmalloc((true_size*sizeof(struct tranzport_cmd))+8, GFP_KERNEL);

	if (!dev->ring_buffer) {
		dev_err(&intf->dev, "Couldn't allocate ring_buffer of size %d\n",true_size);
		goto error;
	}
	dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
	if (!dev->interrupt_in_buffer) {
		dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
		goto error;
	}
	dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
	if (!dev->interrupt_in_urb) {
		dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
		goto error;
	}
	dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
									 udev->descriptor.bMaxPacketSize0;

	if (dev->interrupt_out_endpoint_size !=8)
		dev_warn(&intf->dev, "Interrupt out endpoint size is not 8!)\n");

	dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
	if (!dev->interrupt_out_buffer) {
		dev_err(&intf->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(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
		goto error;
	}
	dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
	if (dev->interrupt_out_endpoint)
		dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;

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

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

	if((retval = device_create_file(&intf->dev, &dev_attr_LightRecord))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackrec))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightTrackmute))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightTracksolo))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightAnysolo))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightLoop))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_LightPunch))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_wheel))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_event))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_dump_state))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_compress_wheel))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_enable))) goto error;
	if((retval = device_create_file(&intf->dev, &dev_attr_offline))) goto error;

	/* let the user know what node this device is now attached to */
	dev_info(&intf->dev, "Tranzport Device #%d now attached to major %d minor %d\n",
		(intf->minor - USB_TRANZPORT_MINOR_BASE), USB_MAJOR, intf->minor);

exit:
	return retval;

error:
	usb_tranzport_delete(dev);

	return retval;
}