|
@@ -3045,6 +3045,203 @@ static int populate_inputset(struct easycap *peasycap)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int alloc_framebuffers(struct easycap *peasycap)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+ void *pbuf;
|
|
|
+
|
|
|
+ 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 (i = 0; i < FRAME_BUFFER_MANY; i++) {
|
|
|
+ for (j = 0; j < FRAME_BUFFER_SIZE/PAGE_SIZE; j++) {
|
|
|
+ if (peasycap->frame_buffer[i][j].pgo)
|
|
|
+ SAM("attempting to reallocate framebuffers\n");
|
|
|
+ else {
|
|
|
+ pbuf = (void *)__get_free_page(GFP_KERNEL);
|
|
|
+ if (!pbuf) {
|
|
|
+ SAM("ERROR: Could not allocate "
|
|
|
+ "framebuffer %i page %i\n", i, j);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ peasycap->allocation_video_page += 1;
|
|
|
+ peasycap->frame_buffer[i][j].pgo = pbuf;
|
|
|
+ }
|
|
|
+ peasycap->frame_buffer[i][j].pto =
|
|
|
+ peasycap->frame_buffer[i][j].pgo;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ peasycap->frame_fill = 0;
|
|
|
+ peasycap->frame_read = 0;
|
|
|
+ JOM(4, "allocation of frame buffers done: %i pages\n", i*j);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int alloc_fieldbuffers(struct easycap *peasycap)
|
|
|
+{
|
|
|
+ int i, j;
|
|
|
+ void *pbuf;
|
|
|
+
|
|
|
+ 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 (i = 0; i < FIELD_BUFFER_MANY; i++) {
|
|
|
+ for (j = 0; j < FIELD_BUFFER_SIZE/PAGE_SIZE; j++) {
|
|
|
+ if (peasycap->field_buffer[i][j].pgo) {
|
|
|
+ SAM("ERROR: attempting to reallocate "
|
|
|
+ "fieldbuffers\n");
|
|
|
+ } else {
|
|
|
+ pbuf = (void *) __get_free_page(GFP_KERNEL);
|
|
|
+ if (!pbuf) {
|
|
|
+ SAM("ERROR: Could not allocate "
|
|
|
+ "fieldbuffer %i page %i\n", i, j);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ peasycap->allocation_video_page += 1;
|
|
|
+ peasycap->field_buffer[i][j].pgo = pbuf;
|
|
|
+ }
|
|
|
+ peasycap->field_buffer[i][j].pto =
|
|
|
+ peasycap->field_buffer[i][j].pgo;
|
|
|
+ }
|
|
|
+ /* TODO: Hardcoded 0x0200 meaning? */
|
|
|
+ peasycap->field_buffer[i][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", i*j);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int alloc_isocbuffers(struct easycap *peasycap)
|
|
|
+{
|
|
|
+ int i;
|
|
|
+ void *pbuf;
|
|
|
+
|
|
|
+ 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 (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
|
|
|
+ pbuf = (void *)__get_free_pages(GFP_KERNEL,
|
|
|
+ VIDEO_ISOC_ORDER);
|
|
|
+ if (!pbuf) {
|
|
|
+ SAM("ERROR: Could not allocate isoc "
|
|
|
+ "video buffer %i\n", i);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+ peasycap->allocation_video_page += BIT(VIDEO_ISOC_ORDER);
|
|
|
+
|
|
|
+ peasycap->video_isoc_buffer[i].pgo = pbuf;
|
|
|
+ peasycap->video_isoc_buffer[i].pto =
|
|
|
+ pbuf + peasycap->video_isoc_buffer_size;
|
|
|
+ peasycap->video_isoc_buffer[i].kount = i;
|
|
|
+ }
|
|
|
+ JOM(4, "allocation of isoc video buffers done: %i pages\n",
|
|
|
+ i * (0x01 << VIDEO_ISOC_ORDER));
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static int create_video_urbs(struct easycap *peasycap)
|
|
|
+{
|
|
|
+ struct urb *purb;
|
|
|
+ struct data_urb *pdata_urb;
|
|
|
+ int i, j;
|
|
|
+
|
|
|
+ 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 (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
|
|
|
+ purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!purb) {
|
|
|
+ SAM("ERROR: usb_alloc_urb returned NULL for buffer "
|
|
|
+ "%i\n", i);
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ peasycap->allocation_video_urb += 1;
|
|
|
+ pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
|
|
|
+ if (!pdata_urb) {
|
|
|
+ SAM("ERROR: Could not allocate struct data_urb.\n");
|
|
|
+ return -ENOMEM;
|
|
|
+ }
|
|
|
+
|
|
|
+ peasycap->allocation_video_struct +=
|
|
|
+ sizeof(struct data_urb);
|
|
|
+
|
|
|
+ pdata_urb->purb = purb;
|
|
|
+ pdata_urb->isbuf = i;
|
|
|
+ pdata_urb->length = 0;
|
|
|
+ list_add_tail(&(pdata_urb->list_head),
|
|
|
+ peasycap->purb_video_head);
|
|
|
+
|
|
|
+ if (!i) {
|
|
|
+ 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[i].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", i);
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
static const struct v4l2_file_operations v4l2_fops = {
|
|
|
.owner = THIS_MODULE,
|
|
|
.open = easycap_open_noinode,
|
|
@@ -3067,7 +3264,7 @@ static int easycap_usb_probe(struct usb_interface *intf,
|
|
|
struct urb *purb;
|
|
|
struct easycap *peasycap;
|
|
|
struct data_urb *pdata_urb;
|
|
|
- int i, j, k, m, rc;
|
|
|
+ int i, j, k, rc;
|
|
|
u8 bInterfaceNumber;
|
|
|
u8 bInterfaceClass;
|
|
|
u8 bInterfaceSubClass;
|
|
@@ -3416,173 +3613,23 @@ static int easycap_usb_probe(struct usb_interface *intf,
|
|
|
*/
|
|
|
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 (peasycap->frame_buffer[k][m].pgo)
|
|
|
- SAM("attempting to reallocate frame "
|
|
|
- " buffers\n");
|
|
|
- else {
|
|
|
- pbuf = (void *)__get_free_page(GFP_KERNEL);
|
|
|
- if (!pbuf) {
|
|
|
- SAM("ERROR: Could not allocate frame "
|
|
|
- "buffer %i page %i\n", k, m);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- 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 (peasycap->field_buffer[k][m].pgo) {
|
|
|
- SAM("ERROR: attempting to reallocate "
|
|
|
- "field buffers\n");
|
|
|
- } else {
|
|
|
- pbuf = (void *) __get_free_page(GFP_KERNEL);
|
|
|
- if (!pbuf) {
|
|
|
- SAM("ERROR: Could not allocate field"
|
|
|
- " buffer %i page %i\n", k, m);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- 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 (!pbuf) {
|
|
|
- SAM("ERROR: Could not allocate isoc video buffer "
|
|
|
- "%i\n", k);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
- peasycap->allocation_video_page +=
|
|
|
- BIT(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 usb */
|
|
|
- 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 (!purb) {
|
|
|
- SAM("ERROR: usb_alloc_urb returned NULL for buffer "
|
|
|
- "%i\n", k);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- peasycap->allocation_video_urb += 1;
|
|
|
- pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
|
|
|
- if (!pdata_urb) {
|
|
|
- SAM("ERROR: Could not allocate struct data_urb.\n");
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
- peasycap->allocation_video_struct +=
|
|
|
- sizeof(struct data_urb);
|
|
|
+ rc = alloc_framebuffers(peasycap);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
|
|
|
- pdata_urb->purb = purb;
|
|
|
- pdata_urb->isbuf = k;
|
|
|
- pdata_urb->length = 0;
|
|
|
- list_add_tail(&(pdata_urb->list_head),
|
|
|
- peasycap->purb_video_head);
|
|
|
+ rc = alloc_fieldbuffers(peasycap);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
|
|
|
- /* Initialize allocated urbs */
|
|
|
- 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");
|
|
|
- }
|
|
|
+ rc = alloc_isocbuffers(peasycap);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
|
|
|
- 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);
|
|
|
+ /* Allocate and initialize video urbs */
|
|
|
+ rc = create_video_urbs(peasycap);
|
|
|
+ if (rc < 0)
|
|
|
+ return rc;
|
|
|
|
|
|
/* Save pointer peasycap in this interface */
|
|
|
usb_set_intfdata(intf, peasycap);
|