Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab019fd4 authored by Ezequiel García's avatar Ezequiel García Committed by Mauro Carvalho Chehab
Browse files

[media] staging: easycap: Split device struct alloc and retrieval code



When the device is probed a driver struct is either
allocated or retrieved.
This operation is logically splitted in several functions.

Signed-off-by: default avatarEzequiel Garcia <elezegarcia@gmail.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent ad3537b5
Loading
Loading
Loading
Loading
+216 −168
Original line number Diff line number Diff line
@@ -2842,87 +2842,92 @@ static void easycap_complete(struct urb *purb)
	return;
}

static const struct v4l2_file_operations v4l2_fops = {
	.owner		= THIS_MODULE,
	.open		= easycap_open_noinode,
	.unlocked_ioctl	= easycap_unlocked_ioctl,
	.poll		= easycap_poll,
	.mmap		= easycap_mmap,
};

/*
 * When the device is plugged, this function is called three times,
 * one for each interface.
 */
static int easycap_usb_probe(struct usb_interface *intf,
			    const struct usb_device_id *id)
static struct easycap *alloc_easycap(u8 bInterfaceNumber)
{
	struct usb_device *usbdev;
	struct usb_host_interface *alt;
	struct usb_endpoint_descriptor *ep;
	struct usb_interface_descriptor *interface;
	struct urb *purb;
	struct easycap *peasycap;
	int ndong;
	struct data_urb *pdata_urb;
	int i, j, k, m, rc;
	u8 bInterfaceNumber;
	u8 bInterfaceClass;
	u8 bInterfaceSubClass;
	void *pbuf;
	int okalt[8], isokalt;
	int okepn[8];
	int okmps[8];
	int maxpacketsize;
	u16 mask;
	s32 value;
	struct easycap_format *peasycap_format;
	int fmtidx;
	struct inputset *inputset;
	int i;

	usbdev = interface_to_usbdev(intf);
	peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
	if (!peasycap) {
		SAY("ERROR: Could not allocate peasycap\n");
		return NULL;
	}

	alt = usb_altnum_to_altsetting(intf, 0);
	if (!alt) {
		SAY("ERROR: usb_host_interface not found\n");
		return -EFAULT;
	if (mutex_lock_interruptible(&mutex_dongle)) {
		SAY("ERROR: cannot lock mutex_dongle\n");
		kfree(peasycap);
		return NULL;
	}

	interface = &alt->desc;
	if (!interface) {
		SAY("ERROR: intf_descriptor is NULL\n");
		return -EFAULT;
	/* Find a free dongle in easycapdc60_dongle array */
	for (i = 0; i < DONGLE_MANY; i++) {

		if ((!easycapdc60_dongle[i].peasycap) &&
		    (!mutex_is_locked(&easycapdc60_dongle[i].mutex_video)) &&
		    (!mutex_is_locked(&easycapdc60_dongle[i].mutex_audio))) {

			easycapdc60_dongle[i].peasycap = peasycap;
			peasycap->isdongle = i;
			JOM(8, "intf[%i]: peasycap-->easycap"
				"_dongle[%i].peasycap\n",
				bInterfaceNumber, i);
			break;
		}
	}

	/* Get properties of probed interface */
	bInterfaceNumber = interface->bInterfaceNumber;
	bInterfaceClass = interface->bInterfaceClass;
	bInterfaceSubClass = interface->bInterfaceSubClass;
	mutex_unlock(&mutex_dongle);

	JOT(4, "intf[%i]: num_altsetting=%i\n",
			bInterfaceNumber, intf->num_altsetting);
	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
		bInterfaceNumber,
		(long int)(intf->cur_altsetting - intf->altsetting));
	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
	if (i >= DONGLE_MANY) {
		SAM("ERROR: too many dongles\n");
		kfree(peasycap);
		return NULL;
	}

	return peasycap;
}

/*
	 * A new struct easycap is always allocated when interface 0 is probed.
	 * It is not possible here to free any existing struct easycap.
	 * This should have been done by easycap_delete() when the device was
	 * physically unplugged.
	 * The allocated struct easycap is saved for later usage when
	 * interfaces 1 and 2 are probed.
 * FIXME: Identify the appropriate pointer peasycap for interfaces
 * 1 and 2. The address of peasycap->pusb_device is reluctantly used
 * for this purpose.
 */
	if (0 == bInterfaceNumber) {
		peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
static struct easycap *get_easycap(struct usb_device *usbdev,
				   u8 bInterfaceNumber)
{
	int i;
	struct easycap *peasycap;

	for (i = 0; i < DONGLE_MANY; i++) {
		if (easycapdc60_dongle[i].peasycap->pusb_device == usbdev) {
			peasycap = easycapdc60_dongle[i].peasycap;
			JOT(8, "intf[%i]: dongle[%i].peasycap\n",
					bInterfaceNumber, i);
			break;
		}
	}
	if (i >= DONGLE_MANY) {
		SAY("ERROR: peasycap is unknown when probing interface %i\n",
			bInterfaceNumber);
		return NULL;
	}
	if (!peasycap) {
			SAY("ERROR: Could not allocate peasycap\n");
			return -ENOMEM;
		SAY("ERROR: peasycap is NULL when probing interface %i\n",
			bInterfaceNumber);
		return NULL;
	}

	return peasycap;
}

		/* Perform urgent initializations */
static void init_easycap(struct easycap *peasycap,
			 struct usb_device *usbdev,
			 struct usb_interface *intf,
			 u8 bInterfaceNumber)
{
	/* Save usb_device and usb_interface */
	peasycap->pusb_device = usbdev;
	peasycap->pusb_interface = intf;

	peasycap->minor = -1;
	kref_init(&peasycap->kref);
	JOM(8, "intf[%i]: after kref_init(..._video) "
@@ -2936,39 +2941,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
	init_waitqueue_head(&peasycap->wq_audio);
	init_waitqueue_head(&peasycap->wq_trigger);

		if (mutex_lock_interruptible(&mutex_dongle)) {
			SAY("ERROR: cannot down mutex_dongle\n");
			return -ERESTARTSYS;
		}

		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
			if ((!easycapdc60_dongle[ndong].peasycap) &&
					(!mutex_is_locked(&easycapdc60_dongle
						[ndong].mutex_video)) &&
					(!mutex_is_locked(&easycapdc60_dongle
						[ndong].mutex_audio))) {
				easycapdc60_dongle[ndong].peasycap = peasycap;
				peasycap->isdongle = ndong;
				JOM(8, "intf[%i]: peasycap-->easycap"
						"_dongle[%i].peasycap\n",
						bInterfaceNumber, ndong);
				break;
			}
		}

		if (DONGLE_MANY <= ndong) {
			SAM("ERROR: too many dongles\n");
			mutex_unlock(&mutex_dongle);
			return -ENOMEM;
		}
		mutex_unlock(&mutex_dongle);

	peasycap->allocation_video_struct = sizeof(struct easycap);

		/* and further initialize the structure */
		peasycap->pusb_device = usbdev;
		peasycap->pusb_interface = intf;

	peasycap->microphone = false;

	peasycap->video_interface = -1;
@@ -2986,44 +2960,45 @@ static int easycap_usb_probe(struct usb_interface *intf,
	peasycap->audio_isoc_buffer_size = -1;

	peasycap->frame_buffer_many = FRAME_BUFFER_MANY;

		/* Dynamically fill in the available formats */
		rc = easycap_video_fillin_formats();
		if (0 > rc) {
			SAM("ERROR: fillin_formats() rc = %i\n", rc);
			return -EFAULT;
}
		JOM(4, "%i formats available\n", rc);

		/* Populate easycap.inputset[] */
static int populate_inputset(struct easycap *peasycap)
{
	struct inputset *inputset;
	struct easycap_format *peasycap_format;
	struct v4l2_pix_format *pix;
	int m, i, k, mask, fmtidx;
	s32 value;

	inputset = peasycap->inputset;

	/* FIXME: peasycap->ntsc is not yet initialized */
	fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;

	m = 0;
	mask = 0;
		for (i = 0; 0xFFFF != easycap_standard[i].mask; i++) {
	for (i = 0; easycap_standard[i].mask != 0xffff; i++) {
		if (fmtidx == easycap_standard[i].v4l2_standard.index) {
			m++;
			for (k = 0; k < INPUT_MANY; k++)
				inputset[k].standard_offset = i;

			mask = easycap_standard[i].mask;
		}
	}
		if (1 != m) {
			SAM("ERROR: "
			    "inputset->standard_offset unpopulated, %i=m\n", m);

	if (m != 1) {
		SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m);
		return -ENOENT;
	}

	peasycap_format = &easycap_format[0];
	m = 0;
	for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
			struct v4l2_pix_format *pix =
				&peasycap_format->v4l2_format.fmt.pix;
			if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) &&
			    pix->field == V4L2_FIELD_NONE &&
			    pix->pixelformat == V4L2_PIX_FMT_UYVY &&
			    pix->width  == 640 && pix->height == 480) {
		pix = &peasycap_format->v4l2_format.fmt.pix;
		if (((peasycap_format->mask & 0x0F) == (mask & 0x0F))
			&& pix->field == V4L2_FIELD_NONE
			&& pix->pixelformat == V4L2_PIX_FMT_UYVY
			&& pix->width  == 640 && pix->height == 480) {
			m++;
			for (k = 0; k < INPUT_MANY; k++)
				inputset[k].format_offset = i;
@@ -3031,13 +3006,13 @@ static int easycap_usb_probe(struct usb_interface *intf,
		}
		peasycap_format++;
	}
		if (1 != m) {
	if (m != 1) {
		SAM("ERROR: inputset[]->format_offset unpopulated\n");
		return -ENOENT;
	}

	m = 0;
		for (i = 0; 0xFFFFFFFF != easycap_control[i].id; i++) {
	for (i = 0; easycap_control[i].id != 0xffffffff; i++) {
		value = easycap_control[i].default_value;
		if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
			m++;
@@ -3058,42 +3033,115 @@ static int easycap_usb_probe(struct usb_interface *intf,
		}
	}

		if (4 != m) {
	if (m != 4) {
		SAM("ERROR: inputset[]->brightness underpopulated\n");
		return -ENOENT;
	}

	for (k = 0; k < INPUT_MANY; k++)
		inputset[k].input = k;
	JOM(4, "populated inputset[]\n");
		JOM(4, "finished initialization\n");
	} else {

	return 0;
}

static const struct v4l2_file_operations v4l2_fops = {
	.owner		= THIS_MODULE,
	.open		= easycap_open_noinode,
	.unlocked_ioctl	= easycap_unlocked_ioctl,
	.poll		= easycap_poll,
	.mmap		= easycap_mmap,
};

/*
		 * FIXME: Identify the appropriate pointer
		 * peasycap for interfaces 1 and 2.
		 * The address of peasycap->pusb_device
		 * is reluctantly used for this purpose.
 * When the device is plugged, this function is called three times,
 * one for each interface.
 */
		for (ndong = 0; ndong < DONGLE_MANY; ndong++) {
			if (usbdev == easycapdc60_dongle[ndong].peasycap->
									pusb_device) {
				peasycap = easycapdc60_dongle[ndong].peasycap;
				JOT(8, "intf[%i]: dongle[%i].peasycap\n",
						bInterfaceNumber, ndong);
				break;
static int easycap_usb_probe(struct usb_interface *intf,
			    const struct usb_device_id *id)
{
	struct usb_device *usbdev;
	struct usb_host_interface *alt;
	struct usb_endpoint_descriptor *ep;
	struct usb_interface_descriptor *interface;
	struct urb *purb;
	struct easycap *peasycap;
	struct data_urb *pdata_urb;
	int i, j, k, m, rc;
	u8 bInterfaceNumber;
	u8 bInterfaceClass;
	u8 bInterfaceSubClass;
	void *pbuf;
	int okalt[8], isokalt;
	int okepn[8];
	int okmps[8];
	int maxpacketsize;

	usbdev = interface_to_usbdev(intf);

	alt = usb_altnum_to_altsetting(intf, 0);
	if (!alt) {
		SAY("ERROR: usb_host_interface not found\n");
		return -EFAULT;
	}

	interface = &alt->desc;
	if (!interface) {
		SAY("ERROR: intf_descriptor is NULL\n");
		return -EFAULT;
	}
		if (DONGLE_MANY <= ndong) {
			SAY("ERROR: peasycap is unknown when probing interface %i\n",
								bInterfaceNumber);
			return -ENODEV;

	/* Get properties of probed interface */
	bInterfaceNumber = interface->bInterfaceNumber;
	bInterfaceClass = interface->bInterfaceClass;
	bInterfaceSubClass = interface->bInterfaceSubClass;

	JOT(4, "intf[%i]: num_altsetting=%i\n",
			bInterfaceNumber, intf->num_altsetting);
	JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
		bInterfaceNumber,
		(long int)(intf->cur_altsetting - intf->altsetting));
	JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
			bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);

	/*
	 * A new struct easycap is always allocated when interface 0 is probed.
	 * It is not possible here to free any existing struct easycap.
	 * This should have been done by easycap_delete() when the device was
	 * physically unplugged.
	 * The allocated struct easycap is saved for later usage when
	 * interfaces 1 and 2 are probed.
	 */
	if (0 == bInterfaceNumber) {
		/*
		 * Alloc structure and save it in a free slot in
		 * easycapdc60_dongle array
		 */
		peasycap = alloc_easycap(bInterfaceNumber);
		if (!peasycap)
			return -ENOMEM;

		/* Perform basic struct initialization */
		init_easycap(peasycap, usbdev, intf, bInterfaceNumber);

		/* Dynamically fill in the available formats */
		rc = easycap_video_fillin_formats();
		if (0 > rc) {
			SAM("ERROR: fillin_formats() rc = %i\n", rc);
			return -EFAULT;
		}
		if (!peasycap) {
			SAY("ERROR: peasycap is NULL when probing interface %i\n",
								bInterfaceNumber);
		JOM(4, "%i formats available\n", rc);

		/* Populate easycap.inputset[] */
		rc = populate_inputset(peasycap);
		if (rc < 0)
			return rc;
		JOM(4, "finished initialization\n");
	} else {
		peasycap = get_easycap(usbdev, bInterfaceNumber);
		if (!peasycap)
			return -ENODEV;
	}
	}

	if ((USB_CLASS_VIDEO == bInterfaceClass) ||
	    (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {