[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: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Hans Verkuil 2012-06-06 01:46:50 -03:00 committed by Mauro Carvalho Chehab
parent 6ba4c432dc
commit de87897af0
2 changed files with 39 additions and 12 deletions

View File

@ -986,13 +986,13 @@ http://www.thedirks.org/winnov/</ulink></para></entry>
<row id="V4L2-PIX-FMT-Y4"> <row id="V4L2-PIX-FMT-Y4">
<entry><constant>V4L2_PIX_FMT_Y4</constant></entry> <entry><constant>V4L2_PIX_FMT_Y4</constant></entry>
<entry>'Y04 '</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> the other bits are set to 0.</entry>
</row> </row>
<row id="V4L2-PIX-FMT-Y6"> <row id="V4L2-PIX-FMT-Y6">
<entry><constant>V4L2_PIX_FMT_Y6</constant></entry> <entry><constant>V4L2_PIX_FMT_Y6</constant></entry>
<entry>'Y06 '</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> the other bits are set to 0.</entry>
</row> </row>
</tbody> </tbody>

View File

@ -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; o = i * pixels_per_line + pixels_read + k;
if (o < len) { if (o < len) {
u8 ch = invert - buffer[k];
got++; got++;
put_user((invert - buffer[k]) << shift, buf + o); put_user(ch << shift, buf + o);
} }
} }
pixels_read += bytes; pixels_read += bytes;
@ -648,8 +649,8 @@ static int qcam_querycap(struct file *file, void *priv,
struct qcam *qcam = video_drvdata(file); struct qcam *qcam = video_drvdata(file);
strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver)); strlcpy(vcap->driver, qcam->v4l2_dev.name, sizeof(vcap->driver));
strlcpy(vcap->card, "B&W Quickcam", sizeof(vcap->card)); strlcpy(vcap->card, "Connectix B&W Quickcam", sizeof(vcap->card));
strlcpy(vcap->bus_info, "parport", sizeof(vcap->bus_info)); strlcpy(vcap->bus_info, qcam->pport->name, sizeof(vcap->bus_info));
vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE; vcap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE;
vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS; vcap->capabilities = vcap->device_caps | V4L2_CAP_DEVICE_CAPS;
return 0; 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->height = qcam->height / qcam->transfer_scale;
pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6; pix->pixelformat = (qcam->bpp == 4) ? V4L2_PIX_FMT_Y4 : V4L2_PIX_FMT_Y6;
pix->field = V4L2_FIELD_NONE; pix->field = V4L2_FIELD_NONE;
pix->bytesperline = qcam->width; pix->bytesperline = pix->width;
pix->sizeimage = qcam->width * qcam->height; pix->sizeimage = pix->width * pix->height;
/* Just a guess */ /* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB; pix->colorspace = V4L2_COLORSPACE_SRGB;
return 0; 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, "4-Bit Monochrome", V4L2_PIX_FMT_Y4,
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}, },
{ 0, 0, 0, { 1, 0, 0,
"6-Bit Monochrome", V4L2_PIX_FMT_Y6, "6-Bit Monochrome", V4L2_PIX_FMT_Y6,
{ 0, 0, 0, 0 } { 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; 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, static ssize_t qcam_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
@ -795,6 +815,11 @@ static ssize_t qcam_read(struct file *file, char __user *buf,
return len; 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) static int qcam_s_ctrl(struct v4l2_ctrl *ctrl)
{ {
struct qcam *qcam = struct qcam *qcam =
@ -828,7 +853,7 @@ static const struct v4l2_file_operations qcam_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = v4l2_fh_open, .open = v4l2_fh_open,
.release = v4l2_fh_release, .release = v4l2_fh_release,
.poll = v4l2_ctrl_poll, .poll = qcam_poll,
.unlocked_ioctl = video_ioctl2, .unlocked_ioctl = video_ioctl2,
.read = qcam_read, .read = qcam_read,
}; };
@ -839,6 +864,7 @@ static const struct v4l2_ioctl_ops qcam_ioctl_ops = {
.vidioc_s_input = qcam_s_input, .vidioc_s_input = qcam_s_input,
.vidioc_enum_input = qcam_enum_input, .vidioc_enum_input = qcam_enum_input,
.vidioc_enum_fmt_vid_cap = qcam_enum_fmt_vid_cap, .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_g_fmt_vid_cap = qcam_g_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap, .vidioc_s_fmt_vid_cap = qcam_s_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = qcam_try_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; return NULL;
v4l2_dev = &qcam->v4l2_dev; 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"); v4l2_err(v4l2_dev, "Could not register v4l2_device\n");
kfree(qcam); kfree(qcam);
return NULL; return NULL;
@ -886,7 +912,7 @@ static struct qcam *qcam_init(struct parport *port)
return NULL; return NULL;
} }
qcam->pport = port; 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); NULL, 0, NULL);
if (qcam->pdev == NULL) { if (qcam->pdev == NULL) {
v4l2_err(v4l2_dev, "couldn't register for %s.\n", port->name); 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; return -ENODEV;
} }
qc_calibrate(qcam); qc_calibrate(qcam);
v4l2_ctrl_handler_setup(&qcam->hdl);
parport_release(qcam->pdev); parport_release(qcam->pdev);