aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/video/pwc/pwc-if.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/pwc/pwc-if.c')
-rw-r--r--drivers/media/video/pwc/pwc-if.c460
1 files changed, 110 insertions, 350 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 01ff643e682..122fbd0081e 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -128,33 +128,23 @@ static struct usb_driver pwc_driver = {
#define MAX_DEV_HINTS 20
#define MAX_ISOC_ERRORS 20
-static int default_fps = 10;
#ifdef CONFIG_USB_PWC_DEBUG
int pwc_trace = PWC_DEBUG_LEVEL;
#endif
static int power_save = -1;
-static int led_on = 100, led_off; /* defaults to LED that is on while in use */
-static int pwc_preferred_compression = 1; /* 0..3 = uncompressed..high */
-static struct {
- int type;
- char serial_number[30];
- int device_node;
- struct pwc_device *pdev;
-} device_hint[MAX_DEV_HINTS];
+static int leds[2] = { 100, 0 };
/***/
-static int pwc_video_open(struct file *file);
static int pwc_video_close(struct file *file);
static ssize_t pwc_video_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos);
static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
-static void pwc_video_release(struct video_device *vfd);
static const struct v4l2_file_operations pwc_fops = {
.owner = THIS_MODULE,
- .open = pwc_video_open,
+ .open = v4l2_fh_open,
.release = pwc_video_close,
.read = pwc_video_read,
.poll = pwc_video_poll,
@@ -163,7 +153,7 @@ static const struct v4l2_file_operations pwc_fops = {
};
static struct video_device pwc_template = {
.name = "Philips Webcam", /* Filled in later */
- .release = pwc_video_release,
+ .release = video_device_release_empty,
.fops = &pwc_fops,
.ioctl_ops = &pwc_ioctl_ops,
};
@@ -191,7 +181,6 @@ static void pwc_snapshot_button(struct pwc_device *pdev, int down)
{
if (down) {
PWC_TRACE("Snapshot button pressed.\n");
- pdev->snapshot_button_status = 1;
} else {
PWC_TRACE("Snapshot button released.\n");
}
@@ -375,6 +364,7 @@ static int pwc_isoc_init(struct pwc_device *pdev)
int i, j, ret;
struct usb_interface *intf;
struct usb_host_interface *idesc = NULL;
+ int compression = 0; /* 0..3 = uncompressed..high */
if (pdev->iso_init)
return 0;
@@ -386,6 +376,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
pdev->visoc_errors = 0;
udev = pdev->udev;
+retry:
+ /* We first try with low compression and then retry with a higher
+ compression setting if there is not enough bandwidth. */
+ ret = pwc_set_video_mode(pdev, pdev->width, pdev->height, pdev->pixfmt,
+ pdev->vframes, &compression, 1);
+
/* Get the current alternate interface, adjust packet size */
intf = usb_ifnum_to_if(udev, 0);
if (intf)
@@ -408,9 +404,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
}
/* Set alternate interface */
- ret = 0;
PWC_DEBUG_OPEN("Setting alternate interface %d\n", pdev->valternate);
ret = usb_set_interface(pdev->udev, 0, pdev->valternate);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ goto retry;
+ }
if (ret < 0)
return ret;
@@ -454,6 +453,12 @@ static int pwc_isoc_init(struct pwc_device *pdev)
/* link */
for (i = 0; i < MAX_ISO_BUFS; i++) {
ret = usb_submit_urb(pdev->urbs[i], GFP_KERNEL);
+ if (ret == -ENOSPC && compression < 3) {
+ compression++;
+ pdev->iso_init = 1;
+ pwc_isoc_cleanup(pdev);
+ goto retry;
+ }
if (ret) {
PWC_ERROR("isoc_init() submit_urb %d failed with error %d\n", i, ret);
pdev->iso_init = 1;
@@ -517,12 +522,11 @@ static void pwc_isoc_cleanup(struct pwc_device *pdev)
PWC_DEBUG_OPEN("<< pwc_isoc_cleanup()\n");
}
-/*
- * Release all queued buffers, no need to take queued_bufs_lock, since all
- * iso urbs have been killed when we're called so pwc_isoc_handler won't run.
- */
static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
{
+ unsigned long flags = 0;
+
+ spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
while (!list_empty(&pdev->queued_bufs)) {
struct pwc_frame_buf *buf;
@@ -531,84 +535,7 @@ static void pwc_cleanup_queued_bufs(struct pwc_device *pdev)
list_del(&buf->list);
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
-}
-
-/*********
- * sysfs
- *********/
-static struct pwc_device *cd_to_pwc(struct device *cd)
-{
- struct video_device *vdev = to_video_device(cd);
- return video_get_drvdata(vdev);
-}
-
-static ssize_t show_pan_tilt(struct device *class_dev,
- struct device_attribute *attr, char *buf)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- return sprintf(buf, "%d %d\n", pdev->pan_angle, pdev->tilt_angle);
-}
-
-static ssize_t store_pan_tilt(struct device *class_dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- int pan, tilt;
- int ret = -EINVAL;
-
- if (strncmp(buf, "reset", 5) == 0)
- ret = pwc_mpt_reset(pdev, 0x3);
-
- else if (sscanf(buf, "%d %d", &pan, &tilt) > 0)
- ret = pwc_mpt_set_angle(pdev, pan, tilt);
-
- if (ret < 0)
- return ret;
- return strlen(buf);
-}
-static DEVICE_ATTR(pan_tilt, S_IRUGO | S_IWUSR, show_pan_tilt,
- store_pan_tilt);
-
-static ssize_t show_snapshot_button_status(struct device *class_dev,
- struct device_attribute *attr, char *buf)
-{
- struct pwc_device *pdev = cd_to_pwc(class_dev);
- int status = pdev->snapshot_button_status;
- pdev->snapshot_button_status = 0;
- return sprintf(buf, "%d\n", status);
-}
-
-static DEVICE_ATTR(button, S_IRUGO | S_IWUSR, show_snapshot_button_status,
- NULL);
-
-static int pwc_create_sysfs_files(struct pwc_device *pdev)
-{
- int rc;
-
- rc = device_create_file(&pdev->vdev.dev, &dev_attr_button);
- if (rc)
- goto err;
- if (pdev->features & FEATURE_MOTOR_PANTILT) {
- rc = device_create_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
- if (rc)
- goto err_button;
- }
-
- return 0;
-
-err_button:
- device_remove_file(&pdev->vdev.dev, &dev_attr_button);
-err:
- PWC_ERROR("Could not create sysfs files.\n");
- return rc;
-}
-
-static void pwc_remove_sysfs_files(struct pwc_device *pdev)
-{
- if (pdev->features & FEATURE_MOTOR_PANTILT)
- device_remove_file(&pdev->vdev.dev, &dev_attr_pan_tilt);
- device_remove_file(&pdev->vdev.dev, &dev_attr_button);
+ spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
#ifdef CONFIG_USB_PWC_DEBUG
@@ -644,85 +571,60 @@ static const char *pwc_sensor_type_to_string(unsigned int sensor_type)
/***************************************************************************/
/* Video4Linux functions */
-static int pwc_video_open(struct file *file)
+int pwc_test_n_set_capt_file(struct pwc_device *pdev, struct file *file)
{
- struct video_device *vdev = video_devdata(file);
- struct pwc_device *pdev;
-
- PWC_DEBUG_OPEN(">> video_open called(vdev = 0x%p).\n", vdev);
-
- pdev = video_get_drvdata(vdev);
- if (!pdev->udev)
- return -ENODEV;
+ int r = 0;
- file->private_data = vdev;
- PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
- return 0;
+ mutex_lock(&pdev->capt_file_lock);
+ if (pdev->capt_file != NULL &&
+ pdev->capt_file != file) {
+ r = -EBUSY;
+ goto leave;
+ }
+ pdev->capt_file = file;
+leave:
+ mutex_unlock(&pdev->capt_file_lock);
+ return r;
}
-static void pwc_video_release(struct video_device *vfd)
+static void pwc_video_release(struct v4l2_device *v)
{
- struct pwc_device *pdev = container_of(vfd, struct pwc_device, vdev);
- int hint;
-
- /* search device_hint[] table if we occupy a slot, by any chance */
- for (hint = 0; hint < MAX_DEV_HINTS; hint++)
- if (device_hint[hint].pdev == pdev)
- device_hint[hint].pdev = NULL;
-
- /* Free intermediate decompression buffer & tables */
- if (pdev->decompress_data != NULL) {
- PWC_DEBUG_MEMORY("Freeing decompression buffer at %p.\n",
- pdev->decompress_data);
- kfree(pdev->decompress_data);
- pdev->decompress_data = NULL;
- }
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
-
+ kfree(pdev->ctrl_buf);
kfree(pdev);
}
static int pwc_video_close(struct file *file)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev;
-
- PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
+ struct pwc_device *pdev = video_drvdata(file);
- pdev = video_get_drvdata(vdev);
if (pdev->capt_file == file) {
vb2_queue_release(&pdev->vb_queue);
pdev->capt_file = NULL;
}
-
- PWC_DEBUG_OPEN("<< video_close()\n");
- return 0;
+ return v4l2_fh_release(file);
}
static ssize_t pwc_video_read(struct file *file, char __user *buf,
size_t count, loff_t *ppos)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (!pdev->udev)
return -ENODEV;
- if (pdev->capt_file != NULL &&
- pdev->capt_file != file)
+ if (pwc_test_n_set_capt_file(pdev, file))
return -EBUSY;
- pdev->capt_file = file;
-
return vb2_read(&pdev->vb_queue, buf, count, ppos,
file->f_flags & O_NONBLOCK);
}
static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (!pdev->udev)
return POLL_ERR;
@@ -732,8 +634,7 @@ static unsigned int pwc_video_poll(struct file *file, poll_table *wait)
static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
{
- struct video_device *vdev = file->private_data;
- struct pwc_device *pdev = video_get_drvdata(vdev);
+ struct pwc_device *pdev = video_drvdata(file);
if (pdev->capt_file != file)
return -EBUSY;
@@ -749,6 +650,7 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
unsigned int sizes[], void *alloc_ctxs[])
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int size;
if (*nbuffers < MIN_FRAMES)
*nbuffers = MIN_FRAMES;
@@ -757,7 +659,9 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *fmt,
*nplanes = 1;
- sizes[0] = PAGE_ALIGN((pdev->abs_max.x * pdev->abs_max.y * 3) / 2);
+ size = pwc_get_size(pdev, MAX_WIDTH, MAX_HEIGHT);
+ sizes[0] = PAGE_ALIGN(pwc_image_sizes[size][0] *
+ pwc_image_sizes[size][1] * 3 / 2);
return 0;
}
@@ -812,56 +716,59 @@ static void buffer_queue(struct vb2_buffer *vb)
unsigned long flags = 0;
spin_lock_irqsave(&pdev->queued_bufs_lock, flags);
- list_add_tail(&buf->list, &pdev->queued_bufs);
+ /* Check the device has not disconnected between prep and queuing */
+ if (pdev->udev)
+ list_add_tail(&buf->list, &pdev->queued_bufs);
+ else
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&pdev->queued_bufs_lock, flags);
}
static int start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ int r;
- if (!pdev->udev)
- return -ENODEV;
+ mutex_lock(&pdev->udevlock);
+ if (!pdev->udev) {
+ r = -ENODEV;
+ goto leave;
+ }
/* Turn on camera and set LEDS on */
pwc_camera_power(pdev, 1);
- if (pdev->power_save) {
- /* Restore video mode */
- pwc_set_video_mode(pdev, pdev->view.x, pdev->view.y,
- pdev->vframes, pdev->vcompression,
- pdev->vsnapshot);
- }
- pwc_set_leds(pdev, led_on, led_off);
+ pwc_set_leds(pdev, leds[0], leds[1]);
- return pwc_isoc_init(pdev);
+ r = pwc_isoc_init(pdev);
+ if (r) {
+ /* If we failed turn camera and LEDS back off */
+ pwc_set_leds(pdev, 0, 0);
+ pwc_camera_power(pdev, 0);
+ /* And cleanup any queued bufs!! */
+ pwc_cleanup_queued_bufs(pdev);
+ }
+leave:
+ mutex_unlock(&pdev->udevlock);
+ return r;
}
static int stop_streaming(struct vb2_queue *vq)
{
struct pwc_device *pdev = vb2_get_drv_priv(vq);
+ mutex_lock(&pdev->udevlock);
if (pdev->udev) {
pwc_set_leds(pdev, 0, 0);
pwc_camera_power(pdev, 0);
pwc_isoc_cleanup(pdev);
}
+ mutex_unlock(&pdev->udevlock);
+
pwc_cleanup_queued_bufs(pdev);
return 0;
}
-static void pwc_lock(struct vb2_queue *vq)
-{
- struct pwc_device *pdev = vb2_get_drv_priv(vq);
- mutex_lock(&pdev->modlock);
-}
-
-static void pwc_unlock(struct vb2_queue *vq)
-{
- struct pwc_device *pdev = vb2_get_drv_priv(vq);
- mutex_unlock(&pdev->modlock);
-}
-
static struct vb2_ops pwc_vb_queue_ops = {
.queue_setup = queue_setup,
.buf_init = buffer_init,
@@ -871,8 +778,6 @@ static struct vb2_ops pwc_vb_queue_ops = {
.buf_queue = buffer_queue,
.start_streaming = start_streaming,
.stop_streaming = stop_streaming,
- .wait_prepare = pwc_unlock,
- .wait_finish = pwc_lock,
};
/***************************************************************************/
@@ -887,9 +792,9 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
struct usb_device *udev = interface_to_usbdev(intf);
struct pwc_device *pdev = NULL;
int vendor_id, product_id, type_id;
- int hint, rc;
+ int rc;
int features = 0;
- int video_nr = -1; /* default: use next available device */
+ int compression = 0;
int my_power_save = power_save;
char serial_number[30], *name;
@@ -1149,28 +1054,15 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return -ENOMEM;
}
pdev->type = type_id;
- pdev->vframes = default_fps;
- strcpy(pdev->serial, serial_number);
pdev->features = features;
- if (vendor_id == 0x046D && product_id == 0x08B5) {
- /* Logitech QuickCam Orbit
- The ranges have been determined experimentally; they may differ from cam to cam.
- Also, the exact ranges left-right and up-down are different for my cam
- */
- pdev->angle_range.pan_min = -7000;
- pdev->angle_range.pan_max = 7000;
- pdev->angle_range.tilt_min = -3000;
- pdev->angle_range.tilt_max = 2500;
- }
pwc_construct(pdev); /* set min/max sizes correct */
- mutex_init(&pdev->modlock);
+ mutex_init(&pdev->capt_file_lock);
mutex_init(&pdev->udevlock);
spin_lock_init(&pdev->queued_bufs_lock);
INIT_LIST_HEAD(&pdev->queued_bufs);
pdev->udev = udev;
- pdev->vcompression = pwc_preferred_compression;
pdev->power_save = my_power_save;
/* Init videobuf2 queue structure */
@@ -1185,35 +1077,21 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
/* Init video_device structure */
memcpy(&pdev->vdev, &pwc_template, sizeof(pwc_template));
- pdev->vdev.parent = &intf->dev;
- pdev->vdev.lock = &pdev->modlock;
strcpy(pdev->vdev.name, name);
+ set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
video_set_drvdata(&pdev->vdev, pdev);
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
PWC_DEBUG_PROBE("Release: %04x\n", pdev->release);
- /* Now search device_hint[] table for a match, so we can hint a node number. */
- for (hint = 0; hint < MAX_DEV_HINTS; hint++) {
- if (((device_hint[hint].type == -1) || (device_hint[hint].type == pdev->type)) &&
- (device_hint[hint].pdev == NULL)) {
- /* so far, so good... try serial number */
- if ((device_hint[hint].serial_number[0] == '*') || !strcmp(device_hint[hint].serial_number, serial_number)) {
- /* match! */
- video_nr = device_hint[hint].device_node;
- PWC_DEBUG_PROBE("Found hint, will try to register as /dev/video%d\n", video_nr);
- break;
- }
- }
+ /* Allocate USB command buffers */
+ pdev->ctrl_buf = kmalloc(sizeof(pdev->cmd_buf), GFP_KERNEL);
+ if (!pdev->ctrl_buf) {
+ PWC_ERROR("Oops, could not allocate memory for pwc_device.\n");
+ rc = -ENOMEM;
+ goto err_free_mem;
}
- /* occupy slot */
- if (hint < MAX_DEV_HINTS)
- device_hint[hint].pdev = pdev;
-
- PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
- usb_set_intfdata(intf, pdev);
-
#ifdef CONFIG_USB_PWC_DEBUG
/* Query sensor type */
if (pwc_get_cmos_sensor(pdev, &rc) >= 0) {
@@ -1227,8 +1105,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
pwc_set_leds(pdev, 0, 0);
/* Setup intial videomode */
- rc = pwc_set_video_mode(pdev, pdev->view_max.x, pdev->view_max.y,
- pdev->vframes, pdev->vcompression, 0);
+ rc = pwc_set_video_mode(pdev, MAX_WIDTH, MAX_HEIGHT,
+ V4L2_PIX_FMT_YUV420, 30, &compression, 1);
if (rc)
goto err_free_mem;
@@ -1239,20 +1117,25 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
goto err_free_mem;
}
- pdev->vdev.ctrl_handler = &pdev->ctrl_handler;
-
/* And powerdown the camera until streaming starts */
pwc_camera_power(pdev, 0);
- rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, video_nr);
- if (rc < 0) {
- PWC_ERROR("Failed to register as video device (%d).\n", rc);
+ /* Register the v4l2_device structure */
+ pdev->v4l2_dev.release = pwc_video_release;
+ rc = v4l2_device_register(&intf->dev, &pdev->v4l2_dev);
+ if (rc) {
+ PWC_ERROR("Failed to register v4l2-device (%d).\n", rc);
goto err_free_controls;
}
- rc = pwc_create_sysfs_files(pdev);
- if (rc)
- goto err_video_unreg;
+ pdev->v4l2_dev.ctrl_handler = &pdev->ctrl_handler;
+ pdev->vdev.v4l2_dev = &pdev->v4l2_dev;
+
+ rc = video_register_device(&pdev->vdev, VFL_TYPE_GRABBER, -1);
+ if (rc < 0) {
+ PWC_ERROR("Failed to register as video device (%d).\n", rc);
+ goto err_unregister_v4l2_dev;
+ }
PWC_INFO("Registered as %s.\n", video_device_node_name(&pdev->vdev));
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
@@ -1261,7 +1144,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (!pdev->button_dev) {
PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
rc = -ENOMEM;
- pwc_remove_sysfs_files(pdev);
goto err_video_unreg;
}
@@ -1279,7 +1161,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
if (rc) {
input_free_device(pdev->button_dev);
pdev->button_dev = NULL;
- pwc_remove_sysfs_files(pdev);
goto err_video_unreg;
}
#endif
@@ -1287,13 +1168,13 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
return 0;
err_video_unreg:
- if (hint < MAX_DEV_HINTS)
- device_hint[hint].pdev = NULL;
video_unregister_device(&pdev->vdev);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&pdev->v4l2_dev);
err_free_controls:
v4l2_ctrl_handler_free(&pdev->ctrl_handler);
err_free_mem:
- usb_set_intfdata(intf, NULL);
+ kfree(pdev->ctrl_buf);
kfree(pdev);
return rc;
}
@@ -1301,27 +1182,26 @@ err_free_mem:
/* The user yanked out the cable... */
static void usb_pwc_disconnect(struct usb_interface *intf)
{
- struct pwc_device *pdev = usb_get_intfdata(intf);
+ struct v4l2_device *v = usb_get_intfdata(intf);
+ struct pwc_device *pdev = container_of(v, struct pwc_device, v4l2_dev);
mutex_lock(&pdev->udevlock);
- mutex_lock(&pdev->modlock);
-
- usb_set_intfdata(intf, NULL);
/* No need to keep the urbs around after disconnection */
pwc_isoc_cleanup(pdev);
- pwc_cleanup_queued_bufs(pdev);
pdev->udev = NULL;
-
- mutex_unlock(&pdev->modlock);
mutex_unlock(&pdev->udevlock);
- pwc_remove_sysfs_files(pdev);
+ pwc_cleanup_queued_bufs(pdev);
+
video_unregister_device(&pdev->vdev);
+ v4l2_device_unregister(&pdev->v4l2_dev);
#ifdef CONFIG_USB_PWC_INPUT_EVDEV
if (pdev->button_dev)
input_unregister_device(pdev->button_dev);
#endif
+
+ v4l2_device_put(&pdev->v4l2_dev);
}
@@ -1329,30 +1209,19 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
* Initialization code & module stuff
*/
-static int fps;
-static int compression = -1;
-static int leds[2] = { -1, -1 };
static unsigned int leds_nargs;
-static char *dev_hint[MAX_DEV_HINTS];
-static unsigned int dev_hint_nargs;
-module_param(fps, int, 0444);
#ifdef CONFIG_USB_PWC_DEBUG
module_param_named(trace, pwc_trace, int, 0644);
#endif
module_param(power_save, int, 0644);
-module_param(compression, int, 0444);
module_param_array(leds, int, &leds_nargs, 0444);
-module_param_array(dev_hint, charp, &dev_hint_nargs, 0444);
-MODULE_PARM_DESC(fps, "Initial frames per second. Varies with model, useful range 5-30");
#ifdef CONFIG_USB_PWC_DEBUG
MODULE_PARM_DESC(trace, "For debugging purposes");
#endif
MODULE_PARM_DESC(power_save, "Turn power saving for new cameras on or off");
-MODULE_PARM_DESC(compression, "Preferred compression quality. Range 0 (uncompressed) to 3 (high compression)");
MODULE_PARM_DESC(leds, "LED on,off time in milliseconds");
-MODULE_PARM_DESC(dev_hint, "Device node hints");
MODULE_DESCRIPTION("Philips & OEM USB webcam driver");
MODULE_AUTHOR("Luc Saillard <luc@saillard.org>");
@@ -1362,122 +1231,13 @@ MODULE_VERSION( PWC_VERSION );
static int __init usb_pwc_init(void)
{
- int i;
-
-#ifdef CONFIG_USB_PWC_DEBUG
- PWC_INFO("Philips webcam module version " PWC_VERSION " loaded.\n");
- PWC_INFO("Supports Philips PCA645/646, PCVC675/680/690, PCVC720[40]/730/740/750 & PCVC830/840.\n");
- PWC_INFO("Also supports the Askey VC010, various Logitech Quickcams, Samsung MPC-C10 and MPC-C30,\n");
- PWC_INFO("the Creative WebCam 5 & Pro Ex, SOTEC Afina Eye and Visionite VCS-UC300 and VCS-UM100.\n");
-
- if (pwc_trace >= 0) {
- PWC_DEBUG_MODULE("Trace options: 0x%04x\n", pwc_trace);
- }
-#endif
-
- if (fps) {
- if (fps < 4 || fps > 30) {
- PWC_ERROR("Framerate out of bounds (4-30).\n");
- return -EINVAL;
- }
- default_fps = fps;
- PWC_DEBUG_MODULE("Default framerate set to %d.\n", default_fps);
- }
-
- if (compression >= 0) {
- if (compression > 3) {
- PWC_ERROR("Invalid compression setting; use a number between 0 (uncompressed) and 3 (high).\n");
- return -EINVAL;
- }
- pwc_preferred_compression = compression;
- PWC_DEBUG_MODULE("Preferred compression set to %d.\n", pwc_preferred_compression);
- }
- if (leds[0] >= 0)
- led_on = leds[0];
- if (leds[1] >= 0)
- led_off = leds[1];
-
- /* Big device node whoopla. Basically, it allows you to assign a
- device node (/dev/videoX) to a camera, based on its type
- & serial number. The format is [type[.serialnumber]:]node.
-
- Any camera that isn't matched by these rules gets the next
- available free device node.
- */
- for (i = 0; i < MAX_DEV_HINTS; i++) {
- char *s, *colon, *dot;
-
- /* This loop also initializes the array */
- device_hint[i].pdev = NULL;
- s = dev_hint[i];
- if (s != NULL && *s != '\0') {
- device_hint[i].type = -1; /* wildcard */
- strcpy(device_hint[i].serial_number, "*");
-
- /* parse string: chop at ':' & '/' */
- colon = dot = s;
- while (*colon != '\0' && *colon != ':')
- colon++;
- while (*dot != '\0' && *dot != '.')
- dot++;
- /* Few sanity checks */
- if (*dot != '\0' && dot > colon) {
- PWC_ERROR("Malformed camera hint: the colon must be after the dot.\n");
- return -EINVAL;
- }
-
- if (*colon == '\0') {
- /* No colon */
- if (*dot != '\0') {
- PWC_ERROR("Malformed camera hint: no colon + device node given.\n");
- return -EINVAL;
- }
- else {
- /* No type or serial number specified, just a number. */
- device_hint[i].device_node =
- simple_strtol(s, NULL, 10);
- }
- }
- else {
- /* There's a colon, so we have at least a type and a device node */
- device_hint[i].type =
- simple_strtol(s, NULL, 10);
- device_hint[i].device_node =
- simple_strtol(colon + 1, NULL, 10);
- if (*dot != '\0') {
- /* There's a serial number as well */
- int k;
-
- dot++;
- k = 0;
- while (*dot != ':' && k < 29) {
- device_hint[i].serial_number[k++] = *dot;
- dot++;
- }
- device_hint[i].serial_number[k] = '\0';
- }
- }
- PWC_TRACE("device_hint[%d]:\n", i);
- PWC_TRACE(" type : %d\n", device_hint[i].type);
- PWC_TRACE(" serial# : %s\n", device_hint[i].serial_number);
- PWC_TRACE(" node : %d\n", device_hint[i].device_node);
- }
- else
- device_hint[i].type = 0; /* not filled */
- } /* ..for MAX_DEV_HINTS */
-
- PWC_DEBUG_PROBE("Registering driver at address 0x%p.\n", &pwc_driver);
return usb_register(&pwc_driver);
}
static void __exit usb_pwc_exit(void)
{
- PWC_DEBUG_MODULE("Deregistering driver.\n");
usb_deregister(&pwc_driver);
- PWC_INFO("Philips webcam module removed.\n");
}
module_init(usb_pwc_init);
module_exit(usb_pwc_exit);
-
-/* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */