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

Commit de87897a authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab
Browse files

[media] bw-qcam: driver and pixfmt documentation fixes



Fix the documentation of the Y4 and Y6 formats.
Fix a poll() issue, add support for enum_frmsizes, set the proper
parent device and fix a few compliance issues.

Tested with an actual Connectix B&W parallel port webcam, both on a
little-endian and a big-endian platform. This driver has never been
so good, doing 320x240 at 1 frame per second :-)

I know, nobody cares, but still it is cool that linux can still support
this old webcam.

Signed-off-by: default avatarHans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 6ba4c432
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -986,13 +986,13 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
	  <row id="V4L2-PIX-FMT-Y4">
	    <entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
	    <entry>'Y04 '</entry>
	    <entry>Old 4-bit greyscale format. Only the least significant 4 bits of each byte are used,
	    <entry>Old 4-bit greyscale format. Only the most significant 4 bits of each byte are used,
the other bits are set to 0.</entry>
	  </row>
	  <row id="V4L2-PIX-FMT-Y6">
	    <entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
	    <entry>'Y06 '</entry>
	    <entry>Old 6-bit greyscale format. Only the least significant 6 bits of each byte are used,
	    <entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
the other bits are set to 0.</entry>
	  </row>
	</tbody>
+37 −10
Original line number Diff line number Diff line
@@ -607,8 +607,9 @@ static long qc_capture(struct qcam *q, char __user *buf, unsigned long len)
				}
				o = i * pixels_per_line + pixels_read + k;
				if (o < len) {
					u8 ch = invert - buffer[k];
					got++;
					put_user((invert - buffer[k]) << shift, buf + o);
					put_user(ch << shift, buf + o);
				}
			}
			pixels_read += bytes;
@@ -648,8 +649,8 @@ static int qcam_querycap(struct file *file, void *priv,
	struct qcam *qcam = video_drvdata(file);

	strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
	strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card));
	strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info));
	strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
	strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
	vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
	vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
	return 0;
@@ -688,8 +689,8 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
	pix->height = qcam->height / qcam->transfer_scale;
	pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
	pix->field = V4L2_FIELD_NONE;
	pix->bytesperline = qcam->width;
	pix->sizeimage = qcam->width * qcam->height;
	pix->bytesperline = pix->width;
	pix->sizeimage = pix->width * pix->height;
	/* Just a guess */
	pix->colorspace = V4L2_COLORSPACE_SRGB;
	return 0;
@@ -757,7 +758,7 @@ static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes
		  "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
		  { 0, 0, 0, 0 }
		},
		{ 0, 0, 0,
		{ 1, 0, 0,
		  "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
		  { 0, 0, 0, 0 }
		},
@@ -772,6 +773,25 @@ static int qcam_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdes
	return 0;
}

static int qcam_enum_framesizes(struct file *file, void *fh,
					 struct v4l2_frmsizeenum *fsize)
{
	static const struct v4l2_frmsize_discrete sizes[] = {
		{  80,  60 },
		{ 160, 120 },
		{ 320, 240 },
	};

	if (fsize->index > 2)
		return -EINVAL;
	if (fsize->pixel_format != V4L2_PIX_FMT_Y4 &&
	    fsize->pixel_format != V4L2_PIX_FMT_Y6)
		return -EINVAL;
	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
	fsize->discrete = sizes[fsize->index];
	return 0;
}

static ssize_t qcam_read(struct file *file, char __user *buf,
		size_t count, loff_t *ppos)
{
@@ -795,6 +815,11 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
	return len;
}

static unsigned int qcam_poll(struct file *filp, poll_table *wait)
{
	return v4l2_ctrl_poll(filp, wait) | POLLIN | POLLRDNORM;
}

static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
{
	struct qcam *qcam =
@@ -828,7 +853,7 @@ static const struct v4l2_file_operations qcam_fops = {
	.owner		= THIS_MODULE,
	.open		= v4l2_fh_open,
	.release	= v4l2_fh_release,
	.poll		= v4l2_ctrl_poll,
	.poll		= qcam_poll,
	.unlocked_ioctl = video_ioctl2,
	.read		= qcam_read,
};
@@ -839,6 +864,7 @@ static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
	.vidioc_s_input      		    = qcam_s_input,
	.vidioc_enum_input   		    = qcam_enum_input,
	.vidioc_enum_fmt_vid_cap 	    = qcam_enum_fmt_vid_cap,
	.vidioc_enum_framesizes		    = qcam_enum_framesizes,
	.vidioc_g_fmt_vid_cap 		    = qcam_g_fmt_vid_cap,
	.vidioc_s_fmt_vid_cap  		    = qcam_s_fmt_vid_cap,
	.vidioc_try_fmt_vid_cap  	    = qcam_try_fmt_vid_cap,
@@ -864,9 +890,9 @@ static struct qcam *qcam_init(struct parport *port)
		return NULL;

	v4l2_dev = &qcam->v4l2_dev;
	strlcpy(v4l2_dev->name, "bw-qcam", sizeof(v4l2_dev->name));
	snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "bw-qcam%d", num_cams);

	if (v4l2_device_register(NULL, v4l2_dev) < 0) {
	if (v4l2_device_register(port->dev, v4l2_dev) < 0) {
		v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
		kfree(qcam);
		return NULL;
@@ -886,7 +912,7 @@ static struct qcam *qcam_init(struct parport *port)
		return NULL;
	}
	qcam->pport = port;
	qcam->pdev = parport_register_device(port, "bw-qcam", NULL, NULL,
	qcam->pdev = parport_register_device(port, v4l2_dev->name, NULL, NULL,
			NULL, 0, NULL);
	if (qcam->pdev == NULL) {
		v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name);
@@ -975,6 +1001,7 @@ static int init_bwqcam(struct parport *port)
		return -ENODEV;
	}
	qc_calibrate(qcam);
	v4l2_ctrl_handler_setup(&qcam->hdl);

	parport_release(qcam->pdev);