diff options
author | Luca Risolia <luca.risolia@studio.unibo.it> | 2007-01-08 09:38:36 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2007-02-21 10:34:20 -0500 |
commit | 2656312724d97ebc2e267e0a9740d51ad7aa9a04 (patch) | |
tree | 57b1cafd03e6c4c461d713748bdf5376873a6027 /drivers/media/video/et61x251 | |
parent | 7e3a0660700ad47ee6e296fe7090d771becfcf96 (diff) |
V4L/DVB (5064): ET61X251 driver updates.
- Implement audio ioctl's and VIDIOC_ENUM_FRAMESIZES
- Documentation updates
- Generic improvements
Signed-off-by: Luca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/et61x251')
-rw-r--r-- | drivers/media/video/et61x251/et61x251.h | 5 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_core.c | 129 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_sensor.h | 4 | ||||
-rw-r--r-- | drivers/media/video/et61x251/et61x251_tas5130d1b.c | 2 |
4 files changed, 88 insertions, 52 deletions
diff --git a/drivers/media/video/et61x251/et61x251.h b/drivers/media/video/et61x251/et61x251.h index 2e5ca4032489..262f98e12409 100644 --- a/drivers/media/video/et61x251/et61x251.h +++ b/drivers/media/video/et61x251/et61x251.h | |||
@@ -171,10 +171,7 @@ struct et61x251_device { | |||
171 | struct et61x251_device* | 171 | struct et61x251_device* |
172 | et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) | 172 | et61x251_match_id(struct et61x251_device* cam, const struct usb_device_id *id) |
173 | { | 173 | { |
174 | if (usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id)) | 174 | return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL; |
175 | return cam; | ||
176 | |||
177 | return NULL; | ||
178 | } | 175 | } |
179 | 176 | ||
180 | 177 | ||
diff --git a/drivers/media/video/et61x251/et61x251_core.c b/drivers/media/video/et61x251/et61x251_core.c index 49792ae8c61c..a6525513cd1e 100644 --- a/drivers/media/video/et61x251/et61x251_core.c +++ b/drivers/media/video/et61x251/et61x251_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * V4L2 driver for ET61X[12]51 PC Camera Controllers * | 2 | * V4L2 driver for ET61X[12]51 PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -48,8 +48,8 @@ | |||
48 | #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" | 48 | #define ET61X251_MODULE_AUTHOR "(C) 2006 Luca Risolia" |
49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" | 49 | #define ET61X251_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>" |
50 | #define ET61X251_MODULE_LICENSE "GPL" | 50 | #define ET61X251_MODULE_LICENSE "GPL" |
51 | #define ET61X251_MODULE_VERSION "1:1.02" | 51 | #define ET61X251_MODULE_VERSION "1:1.04" |
52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 2) | 52 | #define ET61X251_MODULE_VERSION_CODE KERNEL_VERSION(1, 1, 4) |
53 | 53 | ||
54 | /*****************************************************************************/ | 54 | /*****************************************************************************/ |
55 | 55 | ||
@@ -85,7 +85,7 @@ MODULE_PARM_DESC(force_munmap, | |||
85 | "\ndetected camera." | 85 | "\ndetected camera." |
86 | "\n 0 = do not force memory unmapping" | 86 | "\n 0 = do not force memory unmapping" |
87 | "\n 1 = force memory unmapping (save memory)" | 87 | "\n 1 = force memory unmapping (save memory)" |
88 | "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"." | 88 | "\nDefault value is "__MODULE_STRING(ET61X251_FORCE_MUNMAP)"." |
89 | "\n"); | 89 | "\n"); |
90 | 90 | ||
91 | static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = | 91 | static unsigned int frame_timeout[] = {[0 ... ET61X251_MAX_DEVICES-1] = |
@@ -133,7 +133,8 @@ et61x251_request_buffers(struct et61x251_device* cam, u32 count, | |||
133 | 133 | ||
134 | cam->nbuffers = count; | 134 | cam->nbuffers = count; |
135 | while (cam->nbuffers > 0) { | 135 | while (cam->nbuffers > 0) { |
136 | if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize)))) | 136 | if ((buff = vmalloc_32_user(cam->nbuffers * |
137 | PAGE_ALIGN(imagesize)))) | ||
137 | break; | 138 | break; |
138 | cam->nbuffers--; | 139 | cam->nbuffers--; |
139 | } | 140 | } |
@@ -543,10 +544,11 @@ static int et61x251_start_transfer(struct et61x251_device* cam) | |||
543 | { | 544 | { |
544 | struct usb_device *udev = cam->usbdev; | 545 | struct usb_device *udev = cam->usbdev; |
545 | struct urb* urb; | 546 | struct urb* urb; |
546 | const unsigned int wMaxPacketSize[] = {0, 256, 384, 512, 640, 768, 832, | 547 | struct usb_host_interface* altsetting = usb_altnum_to_altsetting( |
547 | 864, 896, 920, 956, 980, 1000, | 548 | usb_ifnum_to_if(udev, 0), |
548 | 1022}; | 549 | ET61X251_ALTERNATE_SETTING); |
549 | const unsigned int psz = wMaxPacketSize[ET61X251_ALTERNATE_SETTING]; | 550 | const unsigned int psz = le16_to_cpu(altsetting-> |
551 | endpoint[0].desc.wMaxPacketSize); | ||
550 | s8 i, j; | 552 | s8 i, j; |
551 | int err = 0; | 553 | int err = 0; |
552 | 554 | ||
@@ -976,29 +978,31 @@ static CLASS_DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR, | |||
976 | static int et61x251_create_sysfs(struct et61x251_device* cam) | 978 | static int et61x251_create_sysfs(struct et61x251_device* cam) |
977 | { | 979 | { |
978 | struct video_device *v4ldev = cam->v4ldev; | 980 | struct video_device *v4ldev = cam->v4ldev; |
979 | int rc; | 981 | int err = 0; |
982 | |||
983 | if ((err = video_device_create_file(v4ldev, &class_device_attr_reg))) | ||
984 | goto err_out; | ||
985 | if ((err = video_device_create_file(v4ldev, &class_device_attr_val))) | ||
986 | goto err_reg; | ||
980 | 987 | ||
981 | rc = video_device_create_file(v4ldev, &class_device_attr_reg); | ||
982 | if (rc) goto err; | ||
983 | rc = video_device_create_file(v4ldev, &class_device_attr_val); | ||
984 | if (rc) goto err_reg; | ||
985 | if (cam->sensor.sysfs_ops) { | 988 | if (cam->sensor.sysfs_ops) { |
986 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_reg); | 989 | if ((err = video_device_create_file(v4ldev, |
987 | if (rc) goto err_val; | 990 | &class_device_attr_i2c_reg))) |
988 | rc = video_device_create_file(v4ldev, &class_device_attr_i2c_val); | 991 | goto err_val; |
989 | if (rc) goto err_i2c_reg; | 992 | if ((err = video_device_create_file(v4ldev, |
993 | &class_device_attr_i2c_val))) | ||
994 | goto err_i2c_reg; | ||
990 | } | 995 | } |
991 | 996 | ||
992 | return 0; | ||
993 | |||
994 | err_i2c_reg: | 997 | err_i2c_reg: |
998 | if (cam->sensor.sysfs_ops) | ||
995 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); | 999 | video_device_remove_file(v4ldev, &class_device_attr_i2c_reg); |
996 | err_val: | 1000 | err_val: |
997 | video_device_remove_file(v4ldev, &class_device_attr_val); | 1001 | video_device_remove_file(v4ldev, &class_device_attr_val); |
998 | err_reg: | 1002 | err_reg: |
999 | video_device_remove_file(v4ldev, &class_device_attr_reg); | 1003 | video_device_remove_file(v4ldev, &class_device_attr_reg); |
1000 | err: | 1004 | err_out: |
1001 | return rc; | 1005 | return err; |
1002 | } | 1006 | } |
1003 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ | 1007 | #endif /* CONFIG_VIDEO_ADV_DEBUG */ |
1004 | 1008 | ||
@@ -1767,10 +1771,10 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1767 | rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; | 1771 | rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L; |
1768 | rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; | 1772 | rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L; |
1769 | 1773 | ||
1770 | if (rect->width < 4) | 1774 | if (rect->width < 16) |
1771 | rect->width = 4; | 1775 | rect->width = 16; |
1772 | if (rect->height < 4) | 1776 | if (rect->height < 16) |
1773 | rect->height = 4; | 1777 | rect->height = 16; |
1774 | if (rect->width > bounds->width) | 1778 | if (rect->width > bounds->width) |
1775 | rect->width = bounds->width; | 1779 | rect->width = bounds->width; |
1776 | if (rect->height > bounds->height) | 1780 | if (rect->height > bounds->height) |
@@ -1784,8 +1788,8 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1784 | if (rect->top + rect->height > bounds->top + bounds->height) | 1788 | if (rect->top + rect->height > bounds->top + bounds->height) |
1785 | rect->top = bounds->top+bounds->height - rect->height; | 1789 | rect->top = bounds->top+bounds->height - rect->height; |
1786 | 1790 | ||
1787 | rect->width &= ~3L; | 1791 | rect->width &= ~15L; |
1788 | rect->height &= ~3L; | 1792 | rect->height &= ~15L; |
1789 | 1793 | ||
1790 | if (ET61X251_PRESERVE_IMGSCALE) { | 1794 | if (ET61X251_PRESERVE_IMGSCALE) { |
1791 | /* Calculate the actual scaling factor */ | 1795 | /* Calculate the actual scaling factor */ |
@@ -1846,6 +1850,35 @@ et61x251_vidioc_s_crop(struct et61x251_device* cam, void __user * arg) | |||
1846 | 1850 | ||
1847 | 1851 | ||
1848 | static int | 1852 | static int |
1853 | et61x251_vidioc_enum_framesizes(struct et61x251_device* cam, void __user * arg) | ||
1854 | { | ||
1855 | struct v4l2_frmsizeenum frmsize; | ||
1856 | |||
1857 | if (copy_from_user(&frmsize, arg, sizeof(frmsize))) | ||
1858 | return -EFAULT; | ||
1859 | |||
1860 | if (frmsize.index != 0) | ||
1861 | return -EINVAL; | ||
1862 | |||
1863 | if (frmsize.pixel_format != V4L2_PIX_FMT_ET61X251 && | ||
1864 | frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8) | ||
1865 | return -EINVAL; | ||
1866 | |||
1867 | frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE; | ||
1868 | frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16; | ||
1869 | frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16; | ||
1870 | frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width; | ||
1871 | frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height; | ||
1872 | memset(&frmsize.reserved, 0, sizeof(frmsize.reserved)); | ||
1873 | |||
1874 | if (copy_to_user(arg, &frmsize, sizeof(frmsize))) | ||
1875 | return -EFAULT; | ||
1876 | |||
1877 | return 0; | ||
1878 | } | ||
1879 | |||
1880 | |||
1881 | static int | ||
1849 | et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) | 1882 | et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) |
1850 | { | 1883 | { |
1851 | struct v4l2_fmtdesc fmtd; | 1884 | struct v4l2_fmtdesc fmtd; |
@@ -1853,6 +1886,9 @@ et61x251_vidioc_enum_fmt(struct et61x251_device* cam, void __user * arg) | |||
1853 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) | 1886 | if (copy_from_user(&fmtd, arg, sizeof(fmtd))) |
1854 | return -EFAULT; | 1887 | return -EFAULT; |
1855 | 1888 | ||
1889 | if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) | ||
1890 | return -EINVAL; | ||
1891 | |||
1856 | if (fmtd.index == 0) { | 1892 | if (fmtd.index == 0) { |
1857 | strcpy(fmtd.description, "bayer rgb"); | 1893 | strcpy(fmtd.description, "bayer rgb"); |
1858 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; | 1894 | fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8; |
@@ -1934,17 +1970,17 @@ et61x251_vidioc_try_s_fmt(struct et61x251_device* cam, unsigned int cmd, | |||
1934 | rect.width = scale * pix->width; | 1970 | rect.width = scale * pix->width; |
1935 | rect.height = scale * pix->height; | 1971 | rect.height = scale * pix->height; |
1936 | 1972 | ||
1937 | if (rect.width < 4) | 1973 | if (rect.width < 16) |
1938 | rect.width = 4; | 1974 | rect.width = 16; |
1939 | if (rect.height < 4) | 1975 | if (rect.height < 16) |
1940 | rect.height = 4; | 1976 | rect.height = 16; |
1941 | if (rect.width > bounds->left + bounds->width - rect.left) | 1977 | if (rect.width > bounds->left + bounds->width - rect.left) |
1942 | rect.width = bounds->left + bounds->width - rect.left; | 1978 | rect.width = bounds->left + bounds->width - rect.left; |
1943 | if (rect.height > bounds->top + bounds->height - rect.top) | 1979 | if (rect.height > bounds->top + bounds->height - rect.top) |
1944 | rect.height = bounds->top + bounds->height - rect.top; | 1980 | rect.height = bounds->top + bounds->height - rect.top; |
1945 | 1981 | ||
1946 | rect.width &= ~3L; | 1982 | rect.width &= ~15L; |
1947 | rect.height &= ~3L; | 1983 | rect.height &= ~15L; |
1948 | 1984 | ||
1949 | { /* adjust the scaling factor */ | 1985 | { /* adjust the scaling factor */ |
1950 | u32 a, b; | 1986 | u32 a, b; |
@@ -2378,6 +2414,9 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2378 | case VIDIOC_S_FMT: | 2414 | case VIDIOC_S_FMT: |
2379 | return et61x251_vidioc_try_s_fmt(cam, cmd, arg); | 2415 | return et61x251_vidioc_try_s_fmt(cam, cmd, arg); |
2380 | 2416 | ||
2417 | case VIDIOC_ENUM_FRAMESIZES: | ||
2418 | return et61x251_vidioc_enum_framesizes(cam, arg); | ||
2419 | |||
2381 | case VIDIOC_G_JPEGCOMP: | 2420 | case VIDIOC_G_JPEGCOMP: |
2382 | return et61x251_vidioc_g_jpegcomp(cam, arg); | 2421 | return et61x251_vidioc_g_jpegcomp(cam, arg); |
2383 | 2422 | ||
@@ -2413,6 +2452,7 @@ static int et61x251_ioctl_v4l2(struct inode* inode, struct file* filp, | |||
2413 | case VIDIOC_QUERYSTD: | 2452 | case VIDIOC_QUERYSTD: |
2414 | case VIDIOC_ENUMSTD: | 2453 | case VIDIOC_ENUMSTD: |
2415 | case VIDIOC_QUERYMENU: | 2454 | case VIDIOC_QUERYMENU: |
2455 | case VIDIOC_ENUM_FRAMEINTERVALS: | ||
2416 | return -EINVAL; | 2456 | return -EINVAL; |
2417 | 2457 | ||
2418 | default: | 2458 | default: |
@@ -2459,6 +2499,7 @@ static const struct file_operations et61x251_fops = { | |||
2459 | .open = et61x251_open, | 2499 | .open = et61x251_open, |
2460 | .release = et61x251_release, | 2500 | .release = et61x251_release, |
2461 | .ioctl = et61x251_ioctl, | 2501 | .ioctl = et61x251_ioctl, |
2502 | .compat_ioctl = v4l_compat_ioctl32, | ||
2462 | .read = et61x251_read, | 2503 | .read = et61x251_read, |
2463 | .poll = et61x251_poll, | 2504 | .poll = et61x251_poll, |
2464 | .mmap = et61x251_mmap, | 2505 | .mmap = et61x251_mmap, |
@@ -2497,7 +2538,7 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2497 | mutex_init(&cam->dev_mutex); | 2538 | mutex_init(&cam->dev_mutex); |
2498 | 2539 | ||
2499 | DBG(2, "ET61X[12]51 PC Camera Controller detected " | 2540 | DBG(2, "ET61X[12]51 PC Camera Controller detected " |
2500 | "(vid/pid 0x%04X/0x%04X)",id->idVendor, id->idProduct); | 2541 | "(vid/pid 0x%04X:0x%04X)",id->idVendor, id->idProduct); |
2501 | 2542 | ||
2502 | for (i = 0; et61x251_sensor_table[i]; i++) { | 2543 | for (i = 0; et61x251_sensor_table[i]; i++) { |
2503 | err = et61x251_sensor_table[i](cam); | 2544 | err = et61x251_sensor_table[i](cam); |
@@ -2550,9 +2591,14 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2550 | 2591 | ||
2551 | #ifdef CONFIG_VIDEO_ADV_DEBUG | 2592 | #ifdef CONFIG_VIDEO_ADV_DEBUG |
2552 | err = et61x251_create_sysfs(cam); | 2593 | err = et61x251_create_sysfs(cam); |
2553 | if (err) | 2594 | if (!err) |
2554 | goto fail2; | 2595 | DBG(2, "Optional device control through 'sysfs' " |
2555 | DBG(2, "Optional device control through 'sysfs' interface ready"); | 2596 | "interface ready"); |
2597 | else | ||
2598 | DBG(2, "Failed to create 'sysfs' interface for optional " | ||
2599 | "device controlling. Error #%d", err); | ||
2600 | #else | ||
2601 | DBG(2, "Optional device control through 'sysfs' interface disabled"); | ||
2556 | #endif | 2602 | #endif |
2557 | 2603 | ||
2558 | usb_set_intfdata(intf, cam); | 2604 | usb_set_intfdata(intf, cam); |
@@ -2561,13 +2607,6 @@ et61x251_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) | |||
2561 | 2607 | ||
2562 | return 0; | 2608 | return 0; |
2563 | 2609 | ||
2564 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
2565 | fail2: | ||
2566 | video_nr[dev_nr] = -1; | ||
2567 | dev_nr = (dev_nr < ET61X251_MAX_DEVICES-1) ? dev_nr+1 : 0; | ||
2568 | mutex_unlock(&cam->dev_mutex); | ||
2569 | video_unregister_device(cam->v4ldev); | ||
2570 | #endif | ||
2571 | fail: | 2610 | fail: |
2572 | if (cam) { | 2611 | if (cam) { |
2573 | kfree(cam->control_buffer); | 2612 | kfree(cam->control_buffer); |
diff --git a/drivers/media/video/et61x251/et61x251_sensor.h b/drivers/media/video/et61x251/et61x251_sensor.h index 65edd08dc386..5fadb5de68bf 100644 --- a/drivers/media/video/et61x251/et61x251_sensor.h +++ b/drivers/media/video/et61x251/et61x251_sensor.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /*************************************************************************** | 1 | /*************************************************************************** |
2 | * API for image sensors connected to ET61X[12]51 PC Camera Controllers * | 2 | * API for image sensors connected to ET61X[12]51 PC Camera Controllers * |
3 | * * | 3 | * * |
4 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 4 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
5 | * * | 5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * | 6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * | 7 | * it under the terms of the GNU General Public License as published by * |
@@ -82,7 +82,7 @@ enum et61x251_i2c_rsta { | |||
82 | ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ | 82 | ET61X251_I2C_RSTA_REPEAT = 0x01, /* repeat start */ |
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define ET61X251_MAX_CTRLS V4L2_CID_LASTP1-V4L2_CID_BASE+10 | 85 | #define ET61X251_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10) |
86 | 86 | ||
87 | struct et61x251_sensor { | 87 | struct et61x251_sensor { |
88 | char name[32]; | 88 | char name[32]; |
diff --git a/drivers/media/video/et61x251/et61x251_tas5130d1b.c b/drivers/media/video/et61x251/et61x251_tas5130d1b.c index a7d65b82b2fb..b06643409842 100644 --- a/drivers/media/video/et61x251/et61x251_tas5130d1b.c +++ b/drivers/media/video/et61x251/et61x251_tas5130d1b.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * | 2 | * Plug-in for TAS5130D1B image sensor connected to the ET61X[12]51 * |
3 | * PC Camera Controllers * | 3 | * PC Camera Controllers * |
4 | * * | 4 | * * |
5 | * Copyright (C) 2006 by Luca Risolia <luca.risolia@studio.unibo.it> * | 5 | * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> * |
6 | * * | 6 | * * |
7 | * This program is free software; you can redistribute it and/or modify * | 7 | * This program is free software; you can redistribute it and/or modify * |
8 | * it under the terms of the GNU General Public License as published by * | 8 | * it under the terms of the GNU General Public License as published by * |