2
* USB ViCam WebCam driver
3
* Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
4
* Christopher L Cheney (ccheney@cheney.cx),
5
* Pavel Machek (pavel@ucw.cz),
6
* John Tyner (jtyner@cs.ucr.edu),
7
* Monroe Williams (monroe@pobox.com)
9
* Supports 3COM HomeConnect PC Digital WebCam
10
* Supports Compro PS39U WebCam
12
* This program is free software; you can redistribute it and/or modify
13
* it under the terms of the GNU General Public License as published by
14
* the Free Software Foundation; either version 2 of the License, or
15
* (at your option) any later version.
17
* This program is distributed in the hope that it will be useful,
18
* but WITHOUT ANY WARRANTY; without even the implied warranty of
19
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20
* GNU General Public License for more details.
22
* You should have received a copy of the GNU General Public License
23
* along with this program; if not, write to the Free Software
24
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
* This source code is based heavily on the CPiA webcam driver which was
27
* written by Peter Pregler, Scott J. Bertin and Johannes Erdfelt
29
* Portions of this code were also copied from usbvideo.c
31
* Special thanks to the whole team at Sourceforge for help making
32
* this driver become a reality. Notably:
33
* Andy Armstrong who reverse engineered the color encoding and
34
* Pavel Machek and Chris Cheney who worked on reverse engineering the
35
* camera controls and wrote the first generation driver.
38
#include <linux/kernel.h>
39
#include <linux/module.h>
40
#include <linux/init.h>
42
#include <linux/usb.h>
43
#include <linux/vmalloc.h>
45
#include <linux/slab.h>
46
#include <linux/mutex.h>
47
#include <linux/firmware.h>
48
#include <linux/ihex.h>
51
// #define VICAM_DEBUG
54
#define ADBG(lineno,fmt,args...) printk(fmt, jiffies, __func__, lineno, ##args)
55
#define DBG(fmt,args...) ADBG((__LINE__),KERN_DEBUG __FILE__"(%ld):%s (%d):"fmt,##args)
57
#define DBG(fmn,args...) do {} while(0)
60
#define DRIVER_AUTHOR "Joe Burks, jburks@wavicle.org"
61
#define DRIVER_DESC "ViCam WebCam Driver"
63
/* Define these values to match your device */
64
#define USB_VICAM_VENDOR_ID 0x04c1
65
#define USB_VICAM_PRODUCT_ID 0x009d
66
#define USB_COMPRO_VENDOR_ID 0x0602
67
#define USB_COMPRO_PRODUCT_ID 0x1001
69
#define VICAM_BYTES_PER_PIXEL 3
70
#define VICAM_MAX_READ_SIZE (512*242+128)
71
#define VICAM_MAX_FRAME_SIZE (VICAM_BYTES_PER_PIXEL*320*240)
72
#define VICAM_FRAMES 2
74
#define VICAM_HEADER_SIZE 64
76
/* rvmalloc / rvfree copied from usbvideo.c
78
* Not sure why these are not yet non-statics which I can reference through
79
* usbvideo.h the same as it is in 2.4.20. I bet this will get fixed sometime
83
static void *rvmalloc(unsigned long size)
88
size = PAGE_ALIGN(size);
89
mem = vmalloc_32(size);
93
memset(mem, 0, size); /* Clear the ram out, no junk to the user */
94
adr = (unsigned long) mem;
96
SetPageReserved(vmalloc_to_page((void *)adr));
104
static void rvfree(void *mem, unsigned long size)
111
adr = (unsigned long) mem;
112
while ((long) size > 0) {
113
ClearPageReserved(vmalloc_to_page((void *)adr));
120
struct vicam_camera {
121
u16 shutter_speed; // capture shutter speed
122
u16 gain; // capture gain
124
u8 *raw_image; // raw data captured from the camera
125
u8 *framebuf; // processed data in RGB24 format
126
u8 *cntrlbuf; // area used to send control msgs
128
struct video_device vdev; // v4l video device
129
struct usb_device *udev; // usb device
131
/* guard against simultaneous accesses to the camera */
132
struct mutex cam_lock;
140
static int vicam_probe( struct usb_interface *intf, const struct usb_device_id *id);
141
static void vicam_disconnect(struct usb_interface *intf);
142
static void read_frame(struct vicam_camera *cam, int framenum);
143
static void vicam_decode_color(const u8 *, u8 *);
145
static int __send_control_msg(struct vicam_camera *cam,
154
/* cp must be memory that has been allocated by kmalloc */
156
status = usb_control_msg(cam->udev,
157
usb_sndctrlpipe(cam->udev, 0),
159
USB_DIR_OUT | USB_TYPE_VENDOR |
160
USB_RECIP_DEVICE, value, index,
163
status = min(status, 0);
166
printk(KERN_INFO "Failed sending control message, error %d.\n",
173
static int send_control_msg(struct vicam_camera *cam,
180
int status = -ENODEV;
181
mutex_lock(&cam->cam_lock);
183
status = __send_control_msg(cam, request, value,
186
mutex_unlock(&cam->cam_lock);
190
initialize_camera(struct vicam_camera *cam)
193
const struct ihex_binrec *rec;
194
const struct firmware *uninitialized_var(fw);
196
err = request_ihex_firmware(&fw, "vicam/firmware.fw", &cam->udev->dev);
198
printk(KERN_ERR "Failed to load \"vicam/firmware.fw\": %d\n",
203
for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
204
memcpy(cam->cntrlbuf, rec->data, be16_to_cpu(rec->len));
206
err = send_control_msg(cam, 0xff, 0, 0,
207
cam->cntrlbuf, be16_to_cpu(rec->len));
212
release_firmware(fw);
218
set_camera_power(struct vicam_camera *cam, int state)
222
if ((status = send_control_msg(cam, 0x50, state, 0, NULL, 0)) < 0)
226
send_control_msg(cam, 0x55, 1, 0, NULL, 0);
233
vicam_ioctl(struct file *file, unsigned int ioctlnr, unsigned long arg)
235
void __user *user_arg = (void __user *)arg;
236
struct vicam_camera *cam = file->private_data;
243
/* query capabilities */
246
struct video_capability b;
249
memset(&b, 0, sizeof(b));
250
strcpy(b.name, "ViCam-based Camera");
251
b.type = VID_TYPE_CAPTURE;
254
b.maxwidth = 320; /* VIDEOSIZE_CIF */
256
b.minwidth = 320; /* VIDEOSIZE_48_48 */
259
if (copy_to_user(user_arg, &b, sizeof(b)))
264
/* get/set video source - we are a camera and nothing else */
267
struct video_channel v;
269
DBG("VIDIOCGCHAN\n");
270
if (copy_from_user(&v, user_arg, sizeof(v))) {
274
if (v.channel != 0) {
280
strcpy(v.name, "Camera");
283
v.type = VIDEO_TYPE_CAMERA;
286
if (copy_to_user(user_arg, &v, sizeof(v)))
295
if (copy_from_user(&v, user_arg, sizeof(v)))
297
DBG("VIDIOCSCHAN %d\n", v);
299
if (retval == 0 && v != 0)
305
/* image properties */
308
struct video_picture vp;
309
DBG("VIDIOCGPICT\n");
310
memset(&vp, 0, sizeof (struct video_picture));
311
vp.brightness = cam->gain << 8;
313
vp.palette = VIDEO_PALETTE_RGB24;
314
if (copy_to_user(user_arg, &vp, sizeof (struct video_picture)))
321
struct video_picture vp;
323
if (copy_from_user(&vp, user_arg, sizeof(vp))) {
328
DBG("VIDIOCSPICT depth = %d, pal = %d\n", vp.depth,
331
cam->gain = vp.brightness >> 8;
334
|| vp.palette != VIDEO_PALETTE_RGB24)
340
/* get/set capture window */
343
struct video_window vw;
355
if (copy_to_user(user_arg, (void *)&vw, sizeof(vw)))
358
// I'm not sure what the deal with a capture window is, it is very poorly described
359
// in the doc. So I won't support it now.
366
struct video_window vw;
368
if (copy_from_user(&vw, user_arg, sizeof(vw))) {
373
DBG("VIDIOCSWIN %d x %d\n", vw.width, vw.height);
375
if ( vw.width != 320 || vw.height != 240 )
384
struct video_mbuf vm;
387
DBG("VIDIOCGMBUF\n");
388
memset(&vm, 0, sizeof (vm));
390
VICAM_MAX_FRAME_SIZE * VICAM_FRAMES;
391
vm.frames = VICAM_FRAMES;
392
for (i = 0; i < VICAM_FRAMES; i++)
393
vm.offsets[i] = VICAM_MAX_FRAME_SIZE * i;
395
if (copy_to_user(user_arg, (void *)&vm, sizeof(vm)))
403
struct video_mmap vm;
406
if (copy_from_user((void *)&vm, user_arg, sizeof(vm))) {
411
DBG("VIDIOCMCAPTURE frame=%d, height=%d, width=%d, format=%d.\n",vm.frame,vm.width,vm.height,vm.format);
413
if ( vm.frame >= VICAM_FRAMES || vm.format != VIDEO_PALETTE_RGB24 )
416
// in theory right here we'd start the image capturing
417
// (fill in a bulk urb and submit it asynchronously)
419
// Instead we're going to do a total hack job for now and
420
// retrieve the frame in VIDIOCSYNC
429
if (copy_from_user((void *)&frame, user_arg, sizeof(int))) {
433
DBG("VIDIOCSYNC: %d\n", frame);
435
read_frame(cam, frame);
436
vicam_decode_color(cam->raw_image,
438
frame * VICAM_MAX_FRAME_SIZE );
443
/* pointless to implement overlay with this camera */
451
/* tuner interface - we have none */
459
/* audio interface - we have none */
465
retval = -ENOIOCTLCMD;
473
vicam_open(struct file *file)
475
struct vicam_camera *cam = video_drvdata(file);
481
"vicam video_device improperly initialized");
485
/* cam_lock/open_count protects us from simultaneous opens
486
* ... for now. we probably shouldn't rely on this fact forever.
489
mutex_lock(&cam->cam_lock);
490
if (cam->open_count > 0) {
492
"vicam_open called on already opened camera");
493
mutex_unlock(&cam->cam_lock);
497
cam->raw_image = kmalloc(VICAM_MAX_READ_SIZE, GFP_KERNEL);
498
if (!cam->raw_image) {
499
mutex_unlock(&cam->cam_lock);
503
cam->framebuf = rvmalloc(VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
504
if (!cam->framebuf) {
505
kfree(cam->raw_image);
506
mutex_unlock(&cam->cam_lock);
510
cam->cntrlbuf = kmalloc(PAGE_SIZE, GFP_KERNEL);
511
if (!cam->cntrlbuf) {
512
kfree(cam->raw_image);
513
rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
514
mutex_unlock(&cam->cam_lock);
518
cam->needsDummyRead = 1;
521
file->private_data = cam;
522
mutex_unlock(&cam->cam_lock);
525
// First upload firmware, then turn the camera on
527
if (!cam->is_initialized) {
528
initialize_camera(cam);
530
cam->is_initialized = 1;
533
set_camera_power(cam, 1);
539
vicam_close(struct file *file)
541
struct vicam_camera *cam = file->private_data;
543
struct usb_device *udev;
547
/* it's not the end of the world if
548
* we fail to turn the camera off.
551
set_camera_power(cam, 0);
553
kfree(cam->raw_image);
554
rvfree(cam->framebuf, VICAM_MAX_FRAME_SIZE * VICAM_FRAMES);
555
kfree(cam->cntrlbuf);
557
mutex_lock(&cam->cam_lock);
560
open_count = cam->open_count;
563
mutex_unlock(&cam->cam_lock);
565
if (!open_count && !udev) {
572
static void vicam_decode_color(const u8 *data, u8 *rgb)
574
/* vicam_decode_color - Convert from Vicam Y-Cr-Cb to RGB
575
* Copyright (C) 2002 Monroe Williams (monroe@pobox.com)
583
data += VICAM_HEADER_SIZE;
585
for( i = 0; i < 240; i++, data += 512 ) {
586
const int y = ( i * 242 ) / 240;
591
if ( y == 242 - 1 ) {
598
for ( j = 0; j < 320; j++, rgb += 3 ) {
599
const int x = ( j * 512 ) / 320;
600
const u8 * const src = &data[x];
602
if ( x == 512 - 1 ) {
606
Cr = ( src[prevX] - src[0] ) +
607
( src[nextX] - src[0] );
610
Cb = ( src[prevY] - src[prevX + prevY] ) +
611
( src[prevY] - src[nextX + prevY] ) +
612
( src[nextY] - src[prevX + nextY] ) +
613
( src[nextY] - src[nextX + nextY] );
616
Y = 1160 * ( src[0] + ( Cr / 2 ) - 16 );
624
if ( ( x ^ i ) & 1 ) {
629
rgb[0] = clamp( ( ( Y + ( 2017 * Cb ) ) +
630
500 ) / 900, 0, 255 );
631
rgb[1] = clamp( ( ( Y - ( 392 * Cb ) -
633
500 ) / 1000, 0, 255 );
634
rgb[2] = clamp( ( ( Y + ( 1594 * Cr ) ) +
635
500 ) / 1300, 0, 255 );
645
read_frame(struct vicam_camera *cam, int framenum)
647
unsigned char *request = cam->cntrlbuf;
652
if (cam->needsDummyRead) {
653
cam->needsDummyRead = 0;
654
read_frame(cam, framenum);
657
memset(request, 0, 16);
658
request[0] = cam->gain; // 0 = 0% gain, FF = 100% gain
660
request[1] = 0; // 512x242 capture
662
request[2] = 0x90; // the function of these two bytes
663
request[3] = 0x07; // is not yet understood
665
if (cam->shutter_speed > 60) {
668
((-15631900 / cam->shutter_speed) + 260533) / 1000;
669
request[4] = realShutter & 0xFF;
670
request[5] = (realShutter >> 8) & 0xFF;
675
realShutter = 15600 / cam->shutter_speed - 1;
678
request[6] = realShutter & 0xFF;
679
request[7] = realShutter >> 8;
682
// Per John Markus Bjørndalen, byte at index 8 causes problems if it isn't 0
684
// bytes 9-15 do not seem to affect exposure or image quality
686
mutex_lock(&cam->cam_lock);
692
n = __send_control_msg(cam, 0x51, 0x80, 0, request, 16);
696
" Problem sending frame capture control message");
700
n = usb_bulk_msg(cam->udev,
701
usb_rcvbulkpipe(cam->udev, cam->bulkEndpoint),
703
512 * 242 + 128, &actual_length, 10000);
706
printk(KERN_ERR "Problem during bulk read of frame data: %d\n",
711
mutex_unlock(&cam->cam_lock);
715
vicam_read( struct file *file, char __user *buf, size_t count, loff_t *ppos )
717
struct vicam_camera *cam = file->private_data;
719
DBG("read %d bytes.\n", (int) count);
721
if (*ppos >= VICAM_MAX_FRAME_SIZE) {
728
vicam_decode_color(cam->raw_image,
730
0 * VICAM_MAX_FRAME_SIZE);
733
count = min_t(size_t, count, VICAM_MAX_FRAME_SIZE - *ppos);
735
if (copy_to_user(buf, &cam->framebuf[*ppos], count)) {
741
if (count == VICAM_MAX_FRAME_SIZE) {
750
vicam_mmap(struct file *file, struct vm_area_struct *vma)
752
// TODO: allocate the raw frame buffer if necessary
753
unsigned long page, pos;
754
unsigned long start = vma->vm_start;
755
unsigned long size = vma->vm_end-vma->vm_start;
756
struct vicam_camera *cam = file->private_data;
761
DBG("vicam_mmap: %ld\n", size);
763
/* We let mmap allocate as much as it wants because Linux was adding 2048 bytes
764
* to the size the application requested for mmap and it was screwing apps up.
765
if (size > VICAM_FRAMES*VICAM_MAX_FRAME_SIZE)
769
pos = (unsigned long)cam->framebuf;
771
page = vmalloc_to_pfn((void *)pos);
772
if (remap_pfn_range(vma, start, page, PAGE_SIZE, PAGE_SHARED))
777
if (size > PAGE_SIZE)
786
static const struct v4l2_file_operations vicam_fops = {
787
.owner = THIS_MODULE,
789
.release = vicam_close,
792
.ioctl = vicam_ioctl,
795
static struct video_device vicam_template = {
796
.name = "ViCam-based USB Camera",
798
.release = video_device_release_empty,
801
/* table of devices that work with this driver */
802
static struct usb_device_id vicam_table[] = {
803
{USB_DEVICE(USB_VICAM_VENDOR_ID, USB_VICAM_PRODUCT_ID)},
804
{USB_DEVICE(USB_COMPRO_VENDOR_ID, USB_COMPRO_PRODUCT_ID)},
805
{} /* Terminating entry */
808
MODULE_DEVICE_TABLE(usb, vicam_table);
810
static struct usb_driver vicam_driver = {
812
.probe = vicam_probe,
813
.disconnect = vicam_disconnect,
814
.id_table = vicam_table
819
* @intf: the interface
822
* Called by the usb core when a new device is connected that it thinks
823
* this driver might be interested in.
826
vicam_probe( struct usb_interface *intf, const struct usb_device_id *id)
828
struct usb_device *dev = interface_to_usbdev(intf);
829
int bulkEndpoint = 0;
830
const struct usb_host_interface *interface;
831
const struct usb_endpoint_descriptor *endpoint;
832
struct vicam_camera *cam;
834
printk(KERN_INFO "ViCam based webcam connected\n");
836
interface = intf->cur_altsetting;
838
DBG(KERN_DEBUG "Interface %d. has %u. endpoints!\n",
839
interface->desc.bInterfaceNumber, (unsigned) (interface->desc.bNumEndpoints));
840
endpoint = &interface->endpoint[0].desc;
842
if (usb_endpoint_is_bulk_in(endpoint)) {
843
/* we found a bulk in endpoint */
844
bulkEndpoint = endpoint->bEndpointAddress;
847
"No bulk in endpoint was found ?! (this is bad)\n");
851
kzalloc(sizeof (struct vicam_camera), GFP_KERNEL)) == NULL) {
853
"could not allocate kernel memory for vicam_camera struct\n");
858
cam->shutter_speed = 15;
860
mutex_init(&cam->cam_lock);
862
memcpy(&cam->vdev, &vicam_template, sizeof(vicam_template));
863
video_set_drvdata(&cam->vdev, cam);
866
cam->bulkEndpoint = bulkEndpoint;
868
if (video_register_device(&cam->vdev, VFL_TYPE_GRABBER, -1) < 0) {
870
printk(KERN_WARNING "video_register_device failed\n");
874
printk(KERN_INFO "ViCam webcam driver now controlling device %s\n",
875
video_device_node_name(&cam->vdev));
877
usb_set_intfdata (intf, cam);
883
vicam_disconnect(struct usb_interface *intf)
886
struct vicam_camera *cam = usb_get_intfdata (intf);
887
usb_set_intfdata (intf, NULL);
889
/* we must unregister the device before taking its
890
* cam_lock. This is because the video open call
891
* holds the same lock as video unregister. if we
892
* unregister inside of the cam_lock and open also
893
* uses the cam_lock, we get deadlock.
896
video_unregister_device(&cam->vdev);
898
/* stop the camera from being used */
900
mutex_lock(&cam->cam_lock);
902
/* mark the camera as gone */
906
/* the only thing left to do is synchronize with
907
* our close/release function on who should release
908
* the camera memory. if there are any users using the
909
* camera, it's their job. if there are no users,
913
open_count = cam->open_count;
915
mutex_unlock(&cam->cam_lock);
921
printk(KERN_DEBUG "ViCam-based WebCam disconnected\n");
930
DBG(KERN_INFO "ViCam-based WebCam driver startup\n");
931
retval = usb_register(&vicam_driver);
933
printk(KERN_WARNING "usb_register failed!\n");
941
"ViCam-based WebCam driver shutdown\n");
943
usb_deregister(&vicam_driver);
946
module_init(usb_vicam_init);
947
module_exit(usb_vicam_exit);
949
MODULE_AUTHOR(DRIVER_AUTHOR);
950
MODULE_DESCRIPTION(DRIVER_DESC);
951
MODULE_LICENSE("GPL");
952
MODULE_FIRMWARE("vicam/firmware.fw");