extractedLnx/linux-2.6.38/drivers/staging/easycap/easycap_main.c_easycap_usb_probe.c
int
easycap_usb_probe(struct usb_interface *pusb_interface, \
const struct usb_device_id *id)
{
struct usb_device *pusb_device, *pusb_device1;
struct usb_host_interface *pusb_host_interface;
struct usb_endpoint_descriptor *pepd;
struct usb_interface_descriptor *pusb_interface_descriptor;
struct usb_interface_assoc_descriptor *pusb_interface_assoc_descriptor;
struct urb *purb;
struct easycap *peasycap;
struct data_urb *pdata_urb;
size_t wMaxPacketSize;
int ISOCwMaxPacketSize;
int BULKwMaxPacketSize;
int INTwMaxPacketSize;
int CTRLwMaxPacketSize;
__u8 bEndpointAddress;
__u8 ISOCbEndpointAddress;
__u8 INTbEndpointAddress;
int isin, 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;
JOT(4, "\n");
if (!dongle_done) {
dongle_done = 1;
for (k = 0; k < DONGLE_MANY; k++) {
easycap_dongle[k].peasycap = (struct easycap *)NULL;
mutex_init(&easycap_dongle[k].mutex_video);
mutex_init(&easycap_dongle[k].mutex_audio);
}
}
peasycap = (struct easycap *)NULL;
if ((struct usb_interface *)NULL == pusb_interface) {
SAY("ERROR: pusb_interface is NULL\n");
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
/*
* GET POINTER TO STRUCTURE usb_device
*/
/*---------------------------------------------------------------------------*/
pusb_device1 = container_of(pusb_interface->dev.parent, \
struct usb_device, dev);
if ((struct usb_device *)NULL == pusb_device1) {
SAY("ERROR: pusb_device1 is NULL\n");
return -EFAULT;
}
pusb_device = usb_get_dev(pusb_device1);
if ((struct usb_device *)NULL == pusb_device) {
SAY("ERROR: pusb_device is NULL\n");
return -EFAULT;
}
if ((unsigned long int)pusb_device1 != (unsigned long int)pusb_device) {
JOT(4, "ERROR: pusb_device1 != pusb_device\n");
return -EFAULT;
}
JOT(4, "bNumConfigurations=%i\n", pusb_device->descriptor.bNumConfigurations);
/*---------------------------------------------------------------------------*/
pusb_host_interface = pusb_interface->cur_altsetting;
if (NULL == pusb_host_interface) {
SAY("ERROR: pusb_host_interface is NULL\n");
return -EFAULT;
}
pusb_interface_descriptor = &(pusb_host_interface->desc);
if (NULL == pusb_interface_descriptor) {
SAY("ERROR: pusb_interface_descriptor is NULL\n");
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
/*
* GET PROPERTIES OF PROBED INTERFACE
*/
/*---------------------------------------------------------------------------*/
bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
bInterfaceClass = pusb_interface_descriptor->bInterfaceClass;
bInterfaceSubClass = pusb_interface_descriptor->bInterfaceSubClass;
JOT(4, "intf[%i]: pusb_interface->num_altsetting=%i\n", \
bInterfaceNumber, pusb_interface->num_altsetting);
JOT(4, "intf[%i]: pusb_interface->cur_altsetting - " \
"pusb_interface->altsetting=%li\n", bInterfaceNumber, \
(long int)(pusb_interface->cur_altsetting - \
pusb_interface->altsetting));
switch (bInterfaceClass) {
case USB_CLASS_AUDIO: {
JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_AUDIO\n", \
bInterfaceNumber, bInterfaceClass); break;
}
case USB_CLASS_VIDEO: {
JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VIDEO\n", \
bInterfaceNumber, bInterfaceClass); break;
}
case USB_CLASS_VENDOR_SPEC: {
JOT(4, "intf[%i]: bInterfaceClass=0x%02X=USB_CLASS_VENDOR_SPEC\n", \
bInterfaceNumber, bInterfaceClass); break;
}
default:
break;
}
switch (bInterfaceSubClass) {
case 0x01: {
JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOCONTROL\n", \
bInterfaceNumber, bInterfaceSubClass); break;
}
case 0x02: {
JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=AUDIOSTREAMING\n", \
bInterfaceNumber, bInterfaceSubClass); break;
}
case 0x03: {
JOT(4, "intf[%i]: bInterfaceSubClass=0x%02X=MIDISTREAMING\n", \
bInterfaceNumber, bInterfaceSubClass); break;
}
default:
break;
}
/*---------------------------------------------------------------------------*/
pusb_interface_assoc_descriptor = pusb_interface->intf_assoc;
if (NULL != pusb_interface_assoc_descriptor) {
JOT(4, "intf[%i]: bFirstInterface=0x%02X bInterfaceCount=0x%02X\n", \
bInterfaceNumber, \
pusb_interface_assoc_descriptor->bFirstInterface, \
pusb_interface_assoc_descriptor->bInterfaceCount);
} else {
JOT(4, "intf[%i]: pusb_interface_assoc_descriptor is NULL\n", \
bInterfaceNumber);
}
/*---------------------------------------------------------------------------*/
/*
* 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 EasyCAP WAS
* PHYSICALLY UNPLUGGED.
*
* THE POINTER peasycap TO THE struct easycap IS REMEMBERED WHEN
* INTERFACES 1 AND 2 ARE PROBED.
*
* IF TWO EasyCAPs ARE PLUGGED IN NEARLY SIMULTANEOUSLY THERE WILL
* BE TROUBLE. BEWARE.
*/
/*---------------------------------------------------------------------------*/
if (0 == bInterfaceNumber) {
peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
if (NULL == peasycap) {
SAY("ERROR: Could not allocate peasycap\n");
return -ENOMEM;
}
SAM("allocated 0x%08lX=peasycap\n", (unsigned long int) peasycap);
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#if defined(EASYCAP_IS_VIDEODEV_CLIENT)
SAM("where 0x%08lX=&peasycap->video_device\n", \
(unsigned long int) &peasycap->video_device);
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
SAM("and 0x%08lX=&peasycap->v4l2_device\n", \
(unsigned long int) &peasycap->v4l2_device);
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
/*---------------------------------------------------------------------------*/
/*
* PERFORM URGENT INTIALIZATIONS ...
*/
/*---------------------------------------------------------------------------*/
strcpy(&peasycap->telltale[0], TELLTALE);
kref_init(&peasycap->kref);
JOM(8, "intf[%i]: after kref_init(..._video) " \
"%i=peasycap->kref.refcount.counter\n", \
bInterfaceNumber, peasycap->kref.refcount.counter);
init_waitqueue_head(&peasycap->wq_video);
init_waitqueue_head(&peasycap->wq_audio);
for (dongle_this = 0; dongle_this < DONGLE_MANY; dongle_this++) {
if (NULL == easycap_dongle[dongle_this].peasycap) {
if (0 == mutex_is_locked(&easycap_dongle\
[dongle_this].mutex_video)) {
if (0 == mutex_is_locked(&easycap_dongle\
[dongle_this].mutex_audio)) {
easycap_dongle\
[dongle_this].peasycap = \
peasycap;
JOM(8, "intf[%i]: peasycap-->easycap" \
"_dongle[%i].peasycap\n", \
bInterfaceNumber, dongle_this);
break;
}
}
}
}
if (DONGLE_MANY <= dongle_this) {
SAM("ERROR: too many dongles\n");
return -ENOMEM;
}
peasycap->allocation_video_struct = sizeof(struct easycap);
peasycap->allocation_video_page = 0;
peasycap->allocation_video_urb = 0;
peasycap->allocation_audio_struct = 0;
peasycap->allocation_audio_page = 0;
peasycap->allocation_audio_urb = 0;
/*---------------------------------------------------------------------------*/
/*
* ... AND FURTHER INITIALIZE THE STRUCTURE
*/
/*---------------------------------------------------------------------------*/
peasycap->pusb_device = pusb_device;
peasycap->pusb_interface = pusb_interface;
peasycap->ilk = 0;
peasycap->microphone = false;
peasycap->video_interface = -1;
peasycap->video_altsetting_on = -1;
peasycap->video_altsetting_off = -1;
peasycap->video_endpointnumber = -1;
peasycap->video_isoc_maxframesize = -1;
peasycap->video_isoc_buffer_size = -1;
peasycap->audio_interface = -1;
peasycap->audio_altsetting_on = -1;
peasycap->audio_altsetting_off = -1;
peasycap->audio_endpointnumber = -1;
peasycap->audio_isoc_maxframesize = -1;
peasycap->audio_isoc_buffer_size = -1;
peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
for (k = 0; k < INPUT_MANY; k++)
peasycap->lost[k] = 0;
peasycap->skip = 0;
peasycap->skipped = 0;
peasycap->offerfields = 0;
/*---------------------------------------------------------------------------*/
/*
* DYNAMICALLY FILL IN THE AVAILABLE FORMATS ...
*/
/*---------------------------------------------------------------------------*/
rc = fillin_formats();
if (0 > rc) {
SAM("ERROR: fillin_formats() returned %i\n", rc);
return -EFAULT;
}
JOM(4, "%i formats available\n", rc);
/*---------------------------------------------------------------------------*/
/*
* ... AND POPULATE easycap.inputset[]
*/
/*---------------------------------------------------------------------------*/
for (k = 0; k < INPUT_MANY; k++) {
peasycap->inputset[k].input_ok = 0;
peasycap->inputset[k].standard_offset_ok = 0;
peasycap->inputset[k].format_offset_ok = 0;
peasycap->inputset[k].brightness_ok = 0;
peasycap->inputset[k].contrast_ok = 0;
peasycap->inputset[k].saturation_ok = 0;
peasycap->inputset[k].hue_ok = 0;
}
if (true == peasycap->ntsc) {
i = 0;
m = 0;
mask = 0;
while (0xFFFF != easycap_standard[i].mask) {
if (NTSC_M == easycap_standard[i].\
v4l2_standard.index) {
m++;
for (k = 0; k < INPUT_MANY; k++) {
peasycap->inputset[k].\
standard_offset = i;
}
mask = easycap_standard[i].mask;
}
i++;
}
} else {
i = 0;
m = 0;
mask = 0;
while (0xFFFF != easycap_standard[i].mask) {
if (PAL_BGHIN == easycap_standard[i].\
v4l2_standard.index) {
m++;
for (k = 0; k < INPUT_MANY; k++) {
peasycap->inputset[k].\
standard_offset = i;
}
mask = easycap_standard[i].mask;
}
i++;
}
}
if (1 != m) {
SAM("MISTAKE: easycap.inputset[].standard_offset " \
"unpopulated, %i=m\n", m);
return -ENOENT;
}
peasycap_format = &easycap_format[0];
i = 0;
m = 0;
while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
if (((peasycap_format->mask & 0x0F) == (mask & 0x0F)) && \
(peasycap_format->\
v4l2_format.fmt.pix.field == \
V4L2_FIELD_NONE) && \
(peasycap_format->\
v4l2_format.fmt.pix.pixelformat == \
V4L2_PIX_FMT_UYVY) && \
(peasycap_format->\
v4l2_format.fmt.pix.width == \
640) && \
(peasycap_format->\
v4l2_format.fmt.pix.height == 480)) {
m++;
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].format_offset = i;
break;
}
peasycap_format++;
i++;
}
if (1 != m) {
SAM("MISTAKE: easycap.inputset[].format_offset unpopulated\n");
return -ENOENT;
}
i = 0;
m = 0;
while (0xFFFFFFFF != easycap_control[i].id) {
value = easycap_control[i].default_value;
if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
m++;
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].brightness = value;
} else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
m++;
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].contrast = value;
} else if (V4L2_CID_SATURATION == easycap_control[i].id) {
m++;
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].saturation = value;
} else if (V4L2_CID_HUE == easycap_control[i].id) {
m++;
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].hue = value;
}
i++;
}
if (4 != m) {
SAM("MISTAKE: easycap.inputset[].brightness,... " \
"underpopulated\n");
return -ENOENT;
}
for (k = 0; k < INPUT_MANY; k++)
peasycap->inputset[k].input = k;
JOM(4, "populated easycap.inputset[]\n");
JOM(4, "finished initialization\n");
} else {
/*---------------------------------------------------------------------------*/
/*
* FOR INTERFACES 1 AND 2 THE POINTER peasycap IS OBTAINED BY ASSUMING
* THAT dongle_this HAS NOT CHANGED SINCE INTERFACE 0 WAS PROBED. IF
* THIS IS NOT THE CASE, FOR EXAMPLE WHEN TWO EASYCAPs ARE PLUGGED IN
* SIMULTANEOUSLY, THERE WILL BE SERIOUS TROUBLE.
*/
/*---------------------------------------------------------------------------*/
if ((0 > dongle_this) || (DONGLE_MANY <= dongle_this)) {
SAY("ERROR: bad dongle count\n");
return -EFAULT;
}
peasycap = easycap_dongle[dongle_this].peasycap;
JOT(8, "intf[%i]: easycap_dongle[%i].peasycap-->peasycap\n", \
bInterfaceNumber, dongle_this);
if ((struct easycap *)NULL == peasycap) {
SAY("ERROR: peasycap is NULL when probing interface %i\n", \
bInterfaceNumber);
return -EFAULT;
}
}
/*---------------------------------------------------------------------------*/
if ((USB_CLASS_VIDEO == bInterfaceClass) || \
(USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
if (-1 == peasycap->video_interface) {
peasycap->video_interface = bInterfaceNumber;
JOM(4, "setting peasycap->video_interface=%i\n", \
peasycap->video_interface);
} else {
if (peasycap->video_interface != bInterfaceNumber) {
SAM("ERROR: attempting to reset " \
"peasycap->video_interface\n");
SAM("...... continuing with " \
"%i=peasycap->video_interface\n", \
peasycap->video_interface);
}
}
} else if ((USB_CLASS_AUDIO == bInterfaceClass) && \
(0x02 == bInterfaceSubClass)) {
if (-1 == peasycap->audio_interface) {
peasycap->audio_interface = bInterfaceNumber;
JOM(4, "setting peasycap->audio_interface=%i\n", \
peasycap->audio_interface);
} else {
if (peasycap->audio_interface != bInterfaceNumber) {
SAM("ERROR: attempting to reset " \
"peasycap->audio_interface\n");
SAM("...... continuing with " \
"%i=peasycap->audio_interface\n", \
peasycap->audio_interface);
}
}
}
/*---------------------------------------------------------------------------*/
/*
* INVESTIGATE ALL ALTSETTINGS.
* DONE IN DETAIL BECAUSE USB DEVICE 05e1:0408 HAS DISPARATE INCARNATIONS.
*/
/*---------------------------------------------------------------------------*/
isokalt = 0;
for (i = 0; i < pusb_interface->num_altsetting; i++) {
pusb_host_interface = &(pusb_interface->altsetting[i]);
if ((struct usb_host_interface *)NULL == pusb_host_interface) {
SAM("ERROR: pusb_host_interface is NULL\n");
return -EFAULT;
}
pusb_interface_descriptor = &(pusb_host_interface->desc);
if ((struct usb_interface_descriptor *)NULL == \
pusb_interface_descriptor) {
SAM("ERROR: pusb_interface_descriptor is NULL\n");
return -EFAULT;
}
JOM(4, "intf[%i]alt[%i]: desc.bDescriptorType=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bDescriptorType);
JOM(4, "intf[%i]alt[%i]: desc.bInterfaceNumber=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceNumber);
JOM(4, "intf[%i]alt[%i]: desc.bAlternateSetting=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bAlternateSetting);
JOM(4, "intf[%i]alt[%i]: desc.bNumEndpoints=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bNumEndpoints);
JOM(4, "intf[%i]alt[%i]: desc.bInterfaceClass=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceClass);
JOM(4, "intf[%i]alt[%i]: desc.bInterfaceSubClass=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceSubClass);
JOM(4, "intf[%i]alt[%i]: desc.bInterfaceProtocol=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->bInterfaceProtocol);
JOM(4, "intf[%i]alt[%i]: desc.iInterface=0x%02X\n", \
bInterfaceNumber, i, pusb_interface_descriptor->iInterface);
ISOCwMaxPacketSize = -1;
BULKwMaxPacketSize = -1;
INTwMaxPacketSize = -1;
CTRLwMaxPacketSize = -1;
ISOCbEndpointAddress = 0;
INTbEndpointAddress = 0;
if (0 == pusb_interface_descriptor->bNumEndpoints)
JOM(4, "intf[%i]alt[%i] has no endpoints\n", \
bInterfaceNumber, i);
/*---------------------------------------------------------------------------*/
for (j = 0; j < pusb_interface_descriptor->bNumEndpoints; j++) {
pepd = &(pusb_host_interface->endpoint[j].desc);
if ((struct usb_endpoint_descriptor *)NULL == pepd) {
SAM("ERROR: pepd is NULL.\n");
SAM("...... skipping\n");
continue;
}
wMaxPacketSize = le16_to_cpu(pepd->wMaxPacketSize);
bEndpointAddress = pepd->bEndpointAddress;
JOM(4, "intf[%i]alt[%i]end[%i]: bEndpointAddress=0x%X\n", \
bInterfaceNumber, i, j, \
pepd->bEndpointAddress);
JOM(4, "intf[%i]alt[%i]end[%i]: bmAttributes=0x%X\n", \
bInterfaceNumber, i, j, \
pepd->bmAttributes);
JOM(4, "intf[%i]alt[%i]end[%i]: wMaxPacketSize=%i\n", \
bInterfaceNumber, i, j, \
pepd->wMaxPacketSize);
JOM(4, "intf[%i]alt[%i]end[%i]: bInterval=%i\n",
bInterfaceNumber, i, j, \
pepd->bInterval);
if (pepd->bEndpointAddress & USB_DIR_IN) {
JOM(4, "intf[%i]alt[%i]end[%i] is an IN endpoint\n",\
bInterfaceNumber, i, j);
isin = 1;
} else {
JOM(4, "intf[%i]alt[%i]end[%i] is an OUT endpoint\n",\
bInterfaceNumber, i, j);
SAM("ERROR: OUT endpoint unexpected\n");
SAM("...... continuing\n");
isin = 0;
}
if ((pepd->bmAttributes & \
USB_ENDPOINT_XFERTYPE_MASK) == \
USB_ENDPOINT_XFER_ISOC) {
JOM(4, "intf[%i]alt[%i]end[%i] is an ISOC endpoint\n",\
bInterfaceNumber, i, j);
if (isin) {
switch (bInterfaceClass) {
case USB_CLASS_VIDEO:
case USB_CLASS_VENDOR_SPEC: {
if (!peasycap) {
SAM("MISTAKE: " \
"peasycap is NULL\n");
return -EFAULT;
}
if (pepd->wMaxPacketSize) {
if (8 > isokalt) {
okalt[isokalt] = i;
JOM(4,\
"%i=okalt[%i]\n", \
okalt[isokalt], \
isokalt);
okepn[isokalt] = \
pepd->\
bEndpointAddress & \
0x0F;
JOM(4,\
"%i=okepn[%i]\n", \
okepn[isokalt], \
isokalt);
okmps[isokalt] = \
le16_to_cpu(pepd->\
wMaxPacketSize);
JOM(4,\
"%i=okmps[%i]\n", \
okmps[isokalt], \
isokalt);
isokalt++;
}
} else {
if (-1 == peasycap->\
video_altsetting_off) {
peasycap->\
video_altsetting_off =\
i;
JOM(4, "%i=video_" \
"altsetting_off " \
"<====\n", \
peasycap->\
video_altsetting_off);
} else {
SAM("ERROR: peasycap" \
"->video_altsetting_" \
"off already set\n");
SAM("...... " \
"continuing with " \
"%i=peasycap->video_" \
"altsetting_off\n", \
peasycap->\
video_altsetting_off);
}
}
break;
}
case USB_CLASS_AUDIO: {
if (0x02 != bInterfaceSubClass)
break;
if (!peasycap) {
SAM("MISTAKE: " \
"peasycap is NULL\n");
return -EFAULT;
}
if (pepd->wMaxPacketSize) {
if (8 > isokalt) {
okalt[isokalt] = i ;
JOM(4,\
"%i=okalt[%i]\n", \
okalt[isokalt], \
isokalt);
okepn[isokalt] = \
pepd->\
bEndpointAddress & \
0x0F;
JOM(4,\
"%i=okepn[%i]\n", \
okepn[isokalt], \
isokalt);
okmps[isokalt] = \
le16_to_cpu(pepd->\
wMaxPacketSize);
JOM(4,\
"%i=okmps[%i]\n",\
okmps[isokalt], \
isokalt);
isokalt++;
}
} else {
if (-1 == peasycap->\
audio_altsetting_off) {
peasycap->\
audio_altsetting_off =\
i;
JOM(4, "%i=audio_" \
"altsetting_off " \
"<====\n", \
peasycap->\
audio_altsetting_off);
} else {
SAM("ERROR: peasycap" \
"->audio_altsetting_" \
"off already set\n");
SAM("...... " \
"continuing with " \
"%i=peasycap->\
audio_altsetting_" \
"off\n",
peasycap->\
audio_altsetting_off);
}
}
break;
}
default:
break;
}
}
} else if ((pepd->bmAttributes & \
USB_ENDPOINT_XFERTYPE_MASK) ==\
USB_ENDPOINT_XFER_BULK) {
JOM(4, "intf[%i]alt[%i]end[%i] is a BULK endpoint\n",\
bInterfaceNumber, i, j);
} else if ((pepd->bmAttributes & \
USB_ENDPOINT_XFERTYPE_MASK) ==\
USB_ENDPOINT_XFER_INT) {
JOM(4, "intf[%i]alt[%i]end[%i] is an INT endpoint\n",\
bInterfaceNumber, i, j);
} else {
JOM(4, "intf[%i]alt[%i]end[%i] is a CTRL endpoint\n",\
bInterfaceNumber, i, j);
}
if (0 == pepd->wMaxPacketSize) {
JOM(4, "intf[%i]alt[%i]end[%i] " \
"has zero packet size\n", \
bInterfaceNumber, i, j);
}
}
}
/*---------------------------------------------------------------------------*/
/*
* PERFORM INITIALIZATION OF THE PROBED INTERFACE
*/
/*---------------------------------------------------------------------------*/
JOM(4, "initialization begins for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber);
switch (bInterfaceNumber) {
/*---------------------------------------------------------------------------*/
/*
* INTERFACE 0 IS THE VIDEO INTERFACE
*/
/*---------------------------------------------------------------------------*/
case 0: {
if (!peasycap) {
SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
}
if (!isokalt) {
SAM("ERROR: no viable video_altsetting_on\n");
return -ENOENT;
} else {
peasycap->video_altsetting_on = okalt[isokalt - 1];
JOM(4, "%i=video_altsetting_on <====\n", \
peasycap->video_altsetting_on);
}
/*---------------------------------------------------------------------------*/
/*
* DECIDE THE VIDEO STREAMING PARAMETERS
*/
/*---------------------------------------------------------------------------*/
peasycap->video_endpointnumber = okepn[isokalt - 1];
JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
maxpacketsize = okmps[isokalt - 1];
if (USB_2_0_MAXPACKETSIZE > maxpacketsize) {
peasycap->video_isoc_maxframesize = maxpacketsize;
} else {
peasycap->video_isoc_maxframesize = \
USB_2_0_MAXPACKETSIZE;
}
JOM(4, "%i=video_isoc_maxframesize\n", \
peasycap->video_isoc_maxframesize);
if (0 >= peasycap->video_isoc_maxframesize) {
SAM("ERROR: bad video_isoc_maxframesize\n");
SAM(" possibly because port is USB 1.1\n");
return -ENOENT;
}
peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
JOM(4, "%i=video_isoc_framesperdesc\n", \
peasycap->video_isoc_framesperdesc);
if (0 >= peasycap->video_isoc_framesperdesc) {
SAM("ERROR: bad video_isoc_framesperdesc\n");
return -ENOENT;
}
peasycap->video_isoc_buffer_size = \
peasycap->video_isoc_maxframesize * \
peasycap->video_isoc_framesperdesc;
JOM(4, "%i=video_isoc_buffer_size\n", \
peasycap->video_isoc_buffer_size);
if ((PAGE_SIZE << VIDEO_ISOC_ORDER) < \
peasycap->video_isoc_buffer_size) {
SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
if (-1 == peasycap->video_interface) {
SAM("MISTAKE: video_interface is unset\n");
return -EFAULT;
}
if (-1 == peasycap->video_altsetting_on) {
SAM("MISTAKE: video_altsetting_on is unset\n");
return -EFAULT;
}
if (-1 == peasycap->video_altsetting_off) {
SAM("MISTAKE: video_interface_off is unset\n");
return -EFAULT;
}
if (-1 == peasycap->video_endpointnumber) {
SAM("MISTAKE: video_endpointnumber is unset\n");
return -EFAULT;
}
if (-1 == peasycap->video_isoc_maxframesize) {
SAM("MISTAKE: video_isoc_maxframesize is unset\n");
return -EFAULT;
}
if (-1 == peasycap->video_isoc_buffer_size) {
SAM("MISTAKE: video_isoc_buffer_size is unset\n");
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
/*
* ALLOCATE MEMORY FOR VIDEO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
*/
/*---------------------------------------------------------------------------*/
INIT_LIST_HEAD(&(peasycap->urb_video_head));
peasycap->purb_video_head = &(peasycap->urb_video_head);
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i frame buffers of size %li\n", \
FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
JOM(4, ".... each scattered over %li pages\n", \
FRAME_BUFFER_SIZE/PAGE_SIZE);
for (k = 0; k < FRAME_BUFFER_MANY; k++) {
for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++) {
if ((void *)NULL != peasycap->frame_buffer[k][m].pgo)
SAM("attempting to reallocate frame " \
" buffers\n");
else {
pbuf = (void *)__get_free_page(GFP_KERNEL);
if ((void *)NULL == pbuf) {
SAM("ERROR: Could not allocate frame "\
"buffer %i page %i\n", k, m);
return -ENOMEM;
} else
peasycap->allocation_video_page += 1;
peasycap->frame_buffer[k][m].pgo = pbuf;
}
peasycap->frame_buffer[k][m].pto = \
peasycap->frame_buffer[k][m].pgo;
}
}
peasycap->frame_fill = 0;
peasycap->frame_read = 0;
JOM(4, "allocation of frame buffers done: %i pages\n", k * \
m);
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i field buffers of size %li\n", \
FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
JOM(4, ".... each scattered over %li pages\n", \
FIELD_BUFFER_SIZE/PAGE_SIZE);
for (k = 0; k < FIELD_BUFFER_MANY; k++) {
for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++) {
if ((void *)NULL != peasycap->field_buffer[k][m].pgo) {
SAM("ERROR: attempting to reallocate " \
"field buffers\n");
} else {
pbuf = (void *) __get_free_page(GFP_KERNEL);
if ((void *)NULL == pbuf) {
SAM("ERROR: Could not allocate field" \
" buffer %i page %i\n", k, m);
return -ENOMEM;
}
else
peasycap->allocation_video_page += 1;
peasycap->field_buffer[k][m].pgo = pbuf;
}
peasycap->field_buffer[k][m].pto = \
peasycap->field_buffer[k][m].pgo;
}
peasycap->field_buffer[k][0].kount = 0x0200;
}
peasycap->field_fill = 0;
peasycap->field_page = 0;
peasycap->field_read = 0;
JOM(4, "allocation of field buffers done: %i pages\n", k * \
m);
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i isoc video buffers of size %i\n", \
VIDEO_ISOC_BUFFER_MANY, \
peasycap->video_isoc_buffer_size);
JOM(4, ".... each occupying contiguous memory pages\n");
for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
pbuf = (void *)__get_free_pages(GFP_KERNEL, VIDEO_ISOC_ORDER);
if (NULL == pbuf) {
SAM("ERROR: Could not allocate isoc video buffer " \
"%i\n", k);
return -ENOMEM;
} else
peasycap->allocation_video_page += \
((unsigned int)(0x01 << VIDEO_ISOC_ORDER));
peasycap->video_isoc_buffer[k].pgo = pbuf;
peasycap->video_isoc_buffer[k].pto = pbuf + \
peasycap->video_isoc_buffer_size;
peasycap->video_isoc_buffer[k].kount = k;
}
JOM(4, "allocation of isoc video buffers done: %i pages\n", \
k * (0x01 << VIDEO_ISOC_ORDER));
/*---------------------------------------------------------------------------*/
/*
* ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
*/
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n", \
peasycap->video_isoc_framesperdesc);
JOM(4, "using %i=peasycap->video_isoc_maxframesize\n", \
peasycap->video_isoc_maxframesize);
JOM(4, "using %i=peasycap->video_isoc_buffer_sizen", \
peasycap->video_isoc_buffer_size);
for (k = 0; k < VIDEO_ISOC_BUFFER_MANY; k++) {
purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc, \
GFP_KERNEL);
if (NULL == purb) {
SAM("ERROR: usb_alloc_urb returned NULL for buffer " \
"%i\n", k);
return -ENOMEM;
} else
peasycap->allocation_video_urb += 1;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
if (NULL == pdata_urb) {
SAM("ERROR: Could not allocate struct data_urb.\n");
return -ENOMEM;
} else
peasycap->allocation_video_struct += \
sizeof(struct data_urb);
pdata_urb->purb = purb;
pdata_urb->isbuf = k;
pdata_urb->length = 0;
list_add_tail(&(pdata_urb->list_head), \
peasycap->purb_video_head);
/*---------------------------------------------------------------------------*/
/*
* ... AND INITIALIZE THEM
*/
/*---------------------------------------------------------------------------*/
if (!k) {
JOM(4, "initializing video urbs thus:\n");
JOM(4, " purb->interval = 1;\n");
JOM(4, " purb->dev = peasycap->pusb_device;\n");
JOM(4, " purb->pipe = usb_rcvisocpipe" \
"(peasycap->pusb_device,%i);\n", \
peasycap->video_endpointnumber);
JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
JOM(4, " purb->transfer_buffer = peasycap->" \
"video_isoc_buffer[.].pgo;\n");
JOM(4, " purb->transfer_buffer_length = %i;\n", \
peasycap->video_isoc_buffer_size);
JOM(4, " purb->complete = easycap_complete;\n");
JOM(4, " purb->context = peasycap;\n");
JOM(4, " purb->start_frame = 0;\n");
JOM(4, " purb->number_of_packets = %i;\n", \
peasycap->video_isoc_framesperdesc);
JOM(4, " for (j = 0; j < %i; j++)\n", \
peasycap->video_isoc_framesperdesc);
JOM(4, " {\n");
JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\
peasycap->video_isoc_maxframesize);
JOM(4, " purb->iso_frame_desc[j].length = %i;\n", \
peasycap->video_isoc_maxframesize);
JOM(4, " }\n");
}
purb->interval = 1;
purb->dev = peasycap->pusb_device;
purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
peasycap->video_endpointnumber);
purb->transfer_flags = URB_ISO_ASAP;
purb->transfer_buffer = peasycap->video_isoc_buffer[k].pgo;
purb->transfer_buffer_length = \
peasycap->video_isoc_buffer_size;
purb->complete = easycap_complete;
purb->context = peasycap;
purb->start_frame = 0;
purb->number_of_packets = peasycap->video_isoc_framesperdesc;
for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
purb->iso_frame_desc[j].offset = j * \
peasycap->video_isoc_maxframesize;
purb->iso_frame_desc[j].length = \
peasycap->video_isoc_maxframesize;
}
}
JOM(4, "allocation of %i struct urb done.\n", k);
/*--------------------------------------------------------------------------*/
/*
* SAVE POINTER peasycap IN THIS INTERFACE.
*/
/*--------------------------------------------------------------------------*/
usb_set_intfdata(pusb_interface, peasycap);
/*---------------------------------------------------------------------------*/
/*
* IT IS ESSENTIAL TO INITIALIZE THE HARDWARE BEFORE, RATHER THAN AFTER,
* THE DEVICE IS REGISTERED, BECAUSE SOME VERSIONS OF THE videodev MODULE
* CALL easycap_open() IMMEDIATELY AFTER REGISTRATION, CAUSING A CLASH.
* BEWARE.
*/
/*---------------------------------------------------------------------------*/
#if defined(PREFER_NTSC)
peasycap->ntsc = true;
JOM(8, "defaulting initially to NTSC\n");
#else
peasycap->ntsc = false;
JOM(8, "defaulting initially to PAL\n");
#endif /*PREFER_NTSC*/
rc = reset(peasycap);
if (0 != rc) {
SAM("ERROR: reset() returned %i\n", rc);
return -EFAULT;
}
/*--------------------------------------------------------------------------*/
/*
* THE VIDEO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
*/
/*--------------------------------------------------------------------------*/
#if (!defined(EASYCAP_IS_VIDEODEV_CLIENT))
if (0 != (usb_register_dev(pusb_interface, &easycap_class))) {
err("Not able to get a minor for this device");
usb_set_intfdata(pusb_interface, NULL);
return -ENODEV;
} else {
(peasycap->registered_video)++;
SAM("easycap attached to minor #%d\n", pusb_interface->minor);
break;
}
/*vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv*/
#else
#if defined(EASYCAP_NEEDS_V4L2_DEVICE_H)
if (0 != (v4l2_device_register(&(pusb_interface->dev), \
&(peasycap->v4l2_device)))) {
SAM("v4l2_device_register() failed\n");
return -ENODEV;
} else {
JOM(4, "registered device instance: %s\n", \
&(peasycap->v4l2_device.name[0]));
}
/*---------------------------------------------------------------------------*/
/*
* FIXME
*
*
* THIS IS BELIEVED TO BE HARMLESS, BUT MAY WELL BE UNNECESSARY OR WRONG:
*/
/*---------------------------------------------------------------------------*/
peasycap->video_device.v4l2_dev = (struct v4l2_device *)NULL;
/*---------------------------------------------------------------------------*/
#endif /*EASYCAP_NEEDS_V4L2_DEVICE_H*/
strcpy(&peasycap->video_device.name[0], "easycapdc60");
#if defined(EASYCAP_NEEDS_V4L2_FOPS)
peasycap->video_device.fops = &v4l2_fops;
#else
peasycap->video_device.fops = &easycap_fops;
#endif /*EASYCAP_NEEDS_V4L2_FOPS*/
peasycap->video_device.minor = -1;
peasycap->video_device.release = (void *)(&videodev_release);
video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
if (0 != (video_register_device(&(peasycap->video_device), \
VFL_TYPE_GRABBER, -1))) {
err("Not able to register with videodev");
videodev_release(&(peasycap->video_device));
return -ENODEV;
} else {
(peasycap->registered_video)++;
SAM("registered with videodev: %i=minor\n", \
peasycap->video_device.minor);
}
#endif /*EASYCAP_IS_VIDEODEV_CLIENT*/
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
break;
}
/*--------------------------------------------------------------------------*/
/*
* INTERFACE 1 IS THE AUDIO CONTROL INTERFACE
* INTERFACE 2 IS THE AUDIO STREAMING INTERFACE
*/
/*--------------------------------------------------------------------------*/
case 1: {
if (!peasycap) {
SAM("ERROR: peasycap is NULL\n");
return -EFAULT;
}
/*--------------------------------------------------------------------------*/
/*
* SAVE POINTER peasycap IN INTERFACE 1
*/
/*--------------------------------------------------------------------------*/
usb_set_intfdata(pusb_interface, peasycap);
JOM(4, "no initialization required for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber);
break;
}
/*--------------------------------------------------------------------------*/
case 2: {
if (!peasycap) {
SAM("MISTAKE: peasycap is NULL\n");
return -EFAULT;
}
if (!isokalt) {
SAM("ERROR: no viable audio_altsetting_on\n");
return -ENOENT;
} else {
peasycap->audio_altsetting_on = okalt[isokalt - 1];
JOM(4, "%i=audio_altsetting_on <====\n", \
peasycap->audio_altsetting_on);
}
peasycap->audio_endpointnumber = okepn[isokalt - 1];
JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
JOM(4, "%i=audio_isoc_maxframesize\n", \
peasycap->audio_isoc_maxframesize);
if (0 >= peasycap->audio_isoc_maxframesize) {
SAM("ERROR: bad audio_isoc_maxframesize\n");
return -ENOENT;
}
if (9 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk |= 0x02;
SAM("hardware is FOUR-CVBS\n");
peasycap->microphone = true;
peasycap->audio_pages_per_fragment = 4;
} else if (256 == peasycap->audio_isoc_maxframesize) {
peasycap->ilk &= ~0x02;
SAM("hardware is CVBS+S-VIDEO\n");
peasycap->microphone = false;
peasycap->audio_pages_per_fragment = 4;
} else {
SAM("hardware is unidentified:\n");
SAM("%i=audio_isoc_maxframesize\n", \
peasycap->audio_isoc_maxframesize);
return -ENOENT;
}
peasycap->audio_bytes_per_fragment = \
peasycap->audio_pages_per_fragment * \
PAGE_SIZE ;
peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY * \
peasycap->audio_pages_per_fragment);
JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
JOM(4, "%6i=audio_pages_per_fragment\n", \
peasycap->audio_pages_per_fragment);
JOM(4, "%6i=audio_bytes_per_fragment\n", \
peasycap->audio_bytes_per_fragment);
JOM(4, "%6i=audio_buffer_page_many\n", \
peasycap->audio_buffer_page_many);
peasycap->audio_isoc_framesperdesc = 128;
JOM(4, "%i=audio_isoc_framesperdesc\n", \
peasycap->audio_isoc_framesperdesc);
if (0 >= peasycap->audio_isoc_framesperdesc) {
SAM("ERROR: bad audio_isoc_framesperdesc\n");
return -ENOENT;
}
peasycap->audio_isoc_buffer_size = \
peasycap->audio_isoc_maxframesize * \
peasycap->audio_isoc_framesperdesc;
JOM(4, "%i=audio_isoc_buffer_size\n", \
peasycap->audio_isoc_buffer_size);
if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
SAM("MISTAKE: audio_isoc_buffer_size bigger "
"than %li=AUDIO_ISOC_BUFFER_SIZE\n", \
AUDIO_ISOC_BUFFER_SIZE);
return -EFAULT;
}
if (-1 == peasycap->audio_interface) {
SAM("MISTAKE: audio_interface is unset\n");
return -EFAULT;
}
if (-1 == peasycap->audio_altsetting_on) {
SAM("MISTAKE: audio_altsetting_on is unset\n");
return -EFAULT;
}
if (-1 == peasycap->audio_altsetting_off) {
SAM("MISTAKE: audio_interface_off is unset\n");
return -EFAULT;
}
if (-1 == peasycap->audio_endpointnumber) {
SAM("MISTAKE: audio_endpointnumber is unset\n");
return -EFAULT;
}
if (-1 == peasycap->audio_isoc_maxframesize) {
SAM("MISTAKE: audio_isoc_maxframesize is unset\n");
return -EFAULT;
}
if (-1 == peasycap->audio_isoc_buffer_size) {
SAM("MISTAKE: audio_isoc_buffer_size is unset\n");
return -EFAULT;
}
/*---------------------------------------------------------------------------*/
/*
* ALLOCATE MEMORY FOR AUDIO BUFFERS. LISTS MUST BE INITIALIZED FIRST.
*/
/*---------------------------------------------------------------------------*/
INIT_LIST_HEAD(&(peasycap->urb_audio_head));
peasycap->purb_audio_head = &(peasycap->urb_audio_head);
JOM(4, "allocating an audio buffer\n");
JOM(4, ".... scattered over %i pages\n", \
peasycap->audio_buffer_page_many);
for (k = 0; k < peasycap->audio_buffer_page_many; k++) {
if ((void *)NULL != peasycap->audio_buffer[k].pgo) {
SAM("ERROR: attempting to reallocate audio buffers\n");
} else {
pbuf = (void *) __get_free_page(GFP_KERNEL);
if ((void *)NULL == pbuf) {
SAM("ERROR: Could not allocate audio " \
"buffer page %i\n", k);
return -ENOMEM;
} else
peasycap->allocation_audio_page += 1;
peasycap->audio_buffer[k].pgo = pbuf;
}
peasycap->audio_buffer[k].pto = peasycap->audio_buffer[k].pgo;
}
peasycap->audio_fill = 0;
peasycap->audio_read = 0;
JOM(4, "allocation of audio buffer done: %i pages\n", k);
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i isoc audio buffers of size %i\n", \
AUDIO_ISOC_BUFFER_MANY, peasycap->audio_isoc_buffer_size);
JOM(4, ".... each occupying contiguous memory pages\n");
for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
if (NULL == pbuf) {
SAM("ERROR: Could not allocate isoc audio buffer " \
"%i\n", k);
return -ENOMEM;
} else
peasycap->allocation_audio_page += \
((unsigned int)(0x01 << AUDIO_ISOC_ORDER));
peasycap->audio_isoc_buffer[k].pgo = pbuf;
peasycap->audio_isoc_buffer[k].pto = pbuf + \
peasycap->audio_isoc_buffer_size;
peasycap->audio_isoc_buffer[k].kount = k;
}
JOM(4, "allocation of isoc audio buffers done.\n");
/*---------------------------------------------------------------------------*/
/*
* ALLOCATE AND INITIALIZE MULTIPLE struct urb ...
*/
/*---------------------------------------------------------------------------*/
JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n", \
peasycap->audio_isoc_framesperdesc);
JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n", \
peasycap->audio_isoc_maxframesize);
JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n", \
peasycap->audio_isoc_buffer_size);
for (k = 0; k < AUDIO_ISOC_BUFFER_MANY; k++) {
purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc, \
GFP_KERNEL);
if (NULL == purb) {
SAM("ERROR: usb_alloc_urb returned NULL for buffer " \
"%i\n", k);
return -ENOMEM;
} else
peasycap->allocation_audio_urb += 1 ;
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
if (NULL == pdata_urb) {
SAM("ERROR: Could not allocate struct data_urb.\n");
return -ENOMEM;
} else
peasycap->allocation_audio_struct += \
sizeof(struct data_urb);
pdata_urb->purb = purb;
pdata_urb->isbuf = k;
pdata_urb->length = 0;
list_add_tail(&(pdata_urb->list_head), \
peasycap->purb_audio_head);
/*---------------------------------------------------------------------------*/
/*
* ... AND INITIALIZE THEM
*/
/*---------------------------------------------------------------------------*/
if (!k) {
JOM(4, "initializing audio urbs thus:\n");
JOM(4, " purb->interval = 1;\n");
JOM(4, " purb->dev = peasycap->pusb_device;\n");
JOM(4, " purb->pipe = usb_rcvisocpipe(peasycap->" \
"pusb_device,%i);\n", \
peasycap->audio_endpointnumber);
JOM(4, " purb->transfer_flags = URB_ISO_ASAP;\n");
JOM(4, " purb->transfer_buffer = " \
"peasycap->audio_isoc_buffer[.].pgo;\n");
JOM(4, " purb->transfer_buffer_length = %i;\n", \
peasycap->audio_isoc_buffer_size);
JOM(4, " purb->complete = easysnd_complete;\n");
JOM(4, " purb->context = peasycap;\n");
JOM(4, " purb->start_frame = 0;\n");
JOM(4, " purb->number_of_packets = %i;\n", \
peasycap->audio_isoc_framesperdesc);
JOM(4, " for (j = 0; j < %i; j++)\n", \
peasycap->audio_isoc_framesperdesc);
JOM(4, " {\n");
JOM(4, " purb->iso_frame_desc[j].offset = j*%i;\n",\
peasycap->audio_isoc_maxframesize);
JOM(4, " purb->iso_frame_desc[j].length = %i;\n", \
peasycap->audio_isoc_maxframesize);
JOM(4, " }\n");
}
purb->interval = 1;
purb->dev = peasycap->pusb_device;
purb->pipe = usb_rcvisocpipe(peasycap->pusb_device, \
peasycap->audio_endpointnumber);
purb->transfer_flags = URB_ISO_ASAP;
purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
purb->transfer_buffer_length = \
peasycap->audio_isoc_buffer_size;
purb->complete = easysnd_complete;
purb->context = peasycap;
purb->start_frame = 0;
purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
for (j = 0; j < peasycap->audio_isoc_framesperdesc; j++) {
purb->iso_frame_desc[j].offset = j * \
peasycap->audio_isoc_maxframesize;
purb->iso_frame_desc[j].length = \
peasycap->audio_isoc_maxframesize;
}
}
JOM(4, "allocation of %i struct urb done.\n", k);
/*---------------------------------------------------------------------------*/
/*
* SAVE POINTER peasycap IN THIS INTERFACE.
*/
/*---------------------------------------------------------------------------*/
usb_set_intfdata(pusb_interface, peasycap);
/*---------------------------------------------------------------------------*/
/*
* THE AUDIO DEVICE CAN BE REGISTERED NOW, AS IT IS READY.
*/
/*---------------------------------------------------------------------------*/
rc = usb_register_dev(pusb_interface, &easysnd_class);
if (0 != rc) {
err("Not able to get a minor for this device.");
usb_set_intfdata(pusb_interface, NULL);
return -ENODEV;
} else {
JOM(8, "kref_get() with %i=peasycap->kref.refcount.counter\n",\
(int)peasycap->kref.refcount.counter);
kref_get(&peasycap->kref);
(peasycap->registered_audio)++;
}
/*---------------------------------------------------------------------------*/
/*
* LET THE USER KNOW WHAT NODE THE AUDIO DEVICE IS ATTACHED TO.
*/
/*---------------------------------------------------------------------------*/
SAM("easysnd attached to minor #%d\n", pusb_interface->minor);
break;
}
/*---------------------------------------------------------------------------*/
/*
* INTERFACES OTHER THAN 0, 1 AND 2 ARE UNEXPECTED
*/
/*---------------------------------------------------------------------------*/
default: {
JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
return -EINVAL;
}
}
JOM(4, "ends successfully for interface %i\n", \
pusb_interface_descriptor->bInterfaceNumber);
return 0;
}
Generated by GNU enscript 1.6.4.