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

[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
...@@ -2842,87 +2842,92 @@ static void easycap_complete(struct urb *purb) ...@@ -2842,87 +2842,92 @@ static void easycap_complete(struct urb *purb)
return; return;
} }
static const struct v4l2_file_operations v4l2_fops = { static struct easycap *alloc_easycap(u8 bInterfaceNumber)
.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)
{ {
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 easycap *peasycap;
int ndong; int i;
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;
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 (mutex_lock_interruptible(&mutex_dongle)) {
if (!alt) { SAY("ERROR: cannot lock mutex_dongle\n");
SAY("ERROR: usb_host_interface not found\n"); kfree(peasycap);
return -EFAULT; return NULL;
} }
interface = &alt->desc; /* Find a free dongle in easycapdc60_dongle array */
if (!interface) { for (i = 0; i < DONGLE_MANY; i++) {
SAY("ERROR: intf_descriptor is NULL\n");
return -EFAULT; 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 */ mutex_unlock(&mutex_dongle);
bInterfaceNumber = interface->bInterfaceNumber;
bInterfaceClass = interface->bInterfaceClass;
bInterfaceSubClass = interface->bInterfaceSubClass;
JOT(4, "intf[%i]: num_altsetting=%i\n", if (i >= DONGLE_MANY) {
bInterfaceNumber, intf->num_altsetting); SAM("ERROR: too many dongles\n");
JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n", kfree(peasycap);
bInterfaceNumber, return NULL;
(long int)(intf->cur_altsetting - intf->altsetting)); }
JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
/* 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. * FIXME: Identify the appropriate pointer peasycap for interfaces
* The allocated struct easycap is saved for later usage when * 1 and 2. The address of peasycap->pusb_device is reluctantly used
* interfaces 1 and 2 are probed. * for this purpose.
*/ */
if (0 == bInterfaceNumber) { static struct easycap *get_easycap(struct usb_device *usbdev,
peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL); 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) { if (!peasycap) {
SAY("ERROR: Could not allocate peasycap\n"); SAY("ERROR: peasycap is NULL when probing interface %i\n",
return -ENOMEM; bInterfaceNumber);
return NULL;
} }
/* Perform urgent initializations */ return peasycap;
}
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; peasycap->minor = -1;
kref_init(&peasycap->kref); kref_init(&peasycap->kref);
JOM(8, "intf[%i]: after kref_init(..._video) " JOM(8, "intf[%i]: after kref_init(..._video) "
...@@ -2936,39 +2941,8 @@ static int easycap_usb_probe(struct usb_interface *intf, ...@@ -2936,39 +2941,8 @@ static int easycap_usb_probe(struct usb_interface *intf,
init_waitqueue_head(&peasycap->wq_audio); init_waitqueue_head(&peasycap->wq_audio);
init_waitqueue_head(&peasycap->wq_trigger); 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); peasycap->allocation_video_struct = sizeof(struct easycap);
/* and further initialize the structure */
peasycap->pusb_device = usbdev;
peasycap->pusb_interface = intf;
peasycap->microphone = false; peasycap->microphone = false;
peasycap->video_interface = -1; peasycap->video_interface = -1;
...@@ -2986,44 +2960,45 @@ static int easycap_usb_probe(struct usb_interface *intf, ...@@ -2986,44 +2960,45 @@ static int easycap_usb_probe(struct usb_interface *intf,
peasycap->audio_isoc_buffer_size = -1; peasycap->audio_isoc_buffer_size = -1;
peasycap->frame_buffer_many = FRAME_BUFFER_MANY; peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
}
/* Dynamically fill in the available formats */ static int populate_inputset(struct easycap *peasycap)
rc = easycap_video_fillin_formats(); {
if (0 > rc) { struct inputset *inputset;
SAM("ERROR: fillin_formats() rc = %i\n", rc); struct easycap_format *peasycap_format;
return -EFAULT; struct v4l2_pix_format *pix;
} int m, i, k, mask, fmtidx;
JOM(4, "%i formats available\n", rc); s32 value;
/* Populate easycap.inputset[] */
inputset = peasycap->inputset; inputset = peasycap->inputset;
/* FIXME: peasycap->ntsc is not yet initialized */
fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN; fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
m = 0; m = 0;
mask = 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) { if (fmtidx == easycap_standard[i].v4l2_standard.index) {
m++; m++;
for (k = 0; k < INPUT_MANY; k++) for (k = 0; k < INPUT_MANY; k++)
inputset[k].standard_offset = i; inputset[k].standard_offset = i;
mask = easycap_standard[i].mask; mask = easycap_standard[i].mask;
} }
} }
if (1 != m) {
SAM("ERROR: " if (m != 1) {
"inputset->standard_offset unpopulated, %i=m\n", m); SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m);
return -ENOENT; return -ENOENT;
} }
peasycap_format = &easycap_format[0]; peasycap_format = &easycap_format[0];
m = 0; m = 0;
for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) { for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
struct v4l2_pix_format *pix = pix = &peasycap_format->v4l2_format.fmt.pix;
&peasycap_format->v4l2_format.fmt.pix; if (((peasycap_format->mask & 0x0F) == (mask & 0x0F))
if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && && pix->field == V4L2_FIELD_NONE
pix->field == V4L2_FIELD_NONE && && pix->pixelformat == V4L2_PIX_FMT_UYVY
pix->pixelformat == V4L2_PIX_FMT_UYVY && && pix->width == 640 && pix->height == 480) {
pix->width == 640 && pix->height == 480) {
m++; m++;
for (k = 0; k < INPUT_MANY; k++) for (k = 0; k < INPUT_MANY; k++)
inputset[k].format_offset = i; inputset[k].format_offset = i;
...@@ -3031,13 +3006,13 @@ static int easycap_usb_probe(struct usb_interface *intf, ...@@ -3031,13 +3006,13 @@ static int easycap_usb_probe(struct usb_interface *intf,
} }
peasycap_format++; peasycap_format++;
} }
if (1 != m) { if (m != 1) {
SAM("ERROR: inputset[]->format_offset unpopulated\n"); SAM("ERROR: inputset[]->format_offset unpopulated\n");
return -ENOENT; return -ENOENT;
} }
m = 0; 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; value = easycap_control[i].default_value;
if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) { if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
m++; m++;
...@@ -3058,42 +3033,115 @@ static int easycap_usb_probe(struct usb_interface *intf, ...@@ -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"); SAM("ERROR: inputset[]->brightness underpopulated\n");
return -ENOENT; return -ENOENT;
} }
for (k = 0; k < INPUT_MANY; k++) for (k = 0; k < INPUT_MANY; k++)
inputset[k].input = k; inputset[k].input = k;
JOM(4, "populated inputset[]\n"); JOM(4, "populated inputset[]\n");
JOM(4, "finished initialization\n");
} else {
/* return 0;
* FIXME: Identify the appropriate pointer }
* peasycap for interfaces 1 and 2.
* The address of peasycap->pusb_device static const struct v4l2_file_operations v4l2_fops = {
* is reluctantly used for this purpose. .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.
*/ */
for (ndong = 0; ndong < DONGLE_MANY; ndong++) { static int easycap_usb_probe(struct usb_interface *intf,
if (usbdev == easycapdc60_dongle[ndong].peasycap-> const struct usb_device_id *id)
pusb_device) { {
peasycap = easycapdc60_dongle[ndong].peasycap; struct usb_device *usbdev;
JOT(8, "intf[%i]: dongle[%i].peasycap\n", struct usb_host_interface *alt;
bInterfaceNumber, ndong); struct usb_endpoint_descriptor *ep;
break; 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", /* Get properties of probed interface */
bInterfaceNumber); bInterfaceNumber = interface->bInterfaceNumber;
return -ENODEV; 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) { JOM(4, "%i formats available\n", rc);
SAY("ERROR: peasycap is NULL when probing interface %i\n",
bInterfaceNumber); /* 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; return -ENODEV;
} }
}
if ((USB_CLASS_VIDEO == bInterfaceClass) || if ((USB_CLASS_VIDEO == bInterfaceClass) ||
(USB_CLASS_VENDOR_SPEC == bInterfaceClass)) { (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment