Commit cd6fcc55 authored by Luca Risolia's avatar Luca Risolia Committed by Greg Kroah-Hartman

[PATCH] USB: SN9C10x driver updates

SN9C10x driver updates:

- Use kzalloc() instead of kmalloc()
- Move some macro definitions from sn9c102.h to sn9c102_core.c
- Use vfree() and vmalloc_32() instead of rvfree() and rvmalloc()
- Fix mmap() sys call
- Documentation updates
Signed-off-by: default avatarLuca Risolia <luca.risolia@studio.unibo.it>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent e988fc8a
...@@ -111,6 +111,12 @@ corresponding modules must be compiled: ...@@ -111,6 +111,12 @@ corresponding modules must be compiled:
# #
CONFIG_VIDEO_DEV=m CONFIG_VIDEO_DEV=m
To enable advanced debugging functionality on the device through /sysfs:
# Multimedia devices
#
CONFIG_VIDEO_ADV_DEBUG=y
# USB support # USB support
# #
CONFIG_USB=m CONFIG_USB=m
...@@ -208,7 +214,8 @@ Default: 2 ...@@ -208,7 +214,8 @@ Default: 2
8. Optional device control through "sysfs" [1] 8. Optional device control through "sysfs" [1]
========================================== ==========================================
It is possible to read and write both the SN9C10x and the image sensor If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
it is possible to read and write both the SN9C10x and the image sensor
registers by using the "sysfs" filesystem interface. registers by using the "sysfs" filesystem interface.
Every time a supported device is recognized, a write-only file named "green" is Every time a supported device is recognized, a write-only file named "green" is
......
...@@ -23,7 +23,8 @@ ...@@ -23,7 +23,8 @@
#include <linux/version.h> #include <linux/version.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/videodev.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/list.h> #include <linux/list.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
...@@ -52,13 +53,6 @@ ...@@ -52,13 +53,6 @@
/*****************************************************************************/ /*****************************************************************************/
#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
#define SN9C102_MODULE_VERSION "1:1.25"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 25)
enum sn9c102_bridge { enum sn9c102_bridge {
BRIDGE_SN9C101 = 0x01, BRIDGE_SN9C101 = 0x01,
BRIDGE_SN9C102 = 0x02, BRIDGE_SN9C102 = 0x02,
...@@ -119,8 +113,6 @@ static DECLARE_MUTEX(sn9c102_sysfs_lock); ...@@ -119,8 +113,6 @@ static DECLARE_MUTEX(sn9c102_sysfs_lock);
static DECLARE_RWSEM(sn9c102_disconnect); static DECLARE_RWSEM(sn9c102_disconnect);
struct sn9c102_device { struct sn9c102_device {
struct device dev;
struct video_device* v4ldev; struct video_device* v4ldev;
enum sn9c102_bridge bridge; enum sn9c102_bridge bridge;
...@@ -161,7 +153,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, ...@@ -161,7 +153,6 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
struct sn9c102_sensor* sensor) struct sn9c102_sensor* sensor)
{ {
cam->sensor = sensor; cam->sensor = sensor;
cam->sensor->dev = &cam->dev;
cam->sensor->usbdev = cam->usbdev; cam->sensor->usbdev = cam->usbdev;
} }
...@@ -174,14 +165,19 @@ sn9c102_attach_sensor(struct sn9c102_device* cam, ...@@ -174,14 +165,19 @@ sn9c102_attach_sensor(struct sn9c102_device* cam,
do { \ do { \
if (debug >= (level)) { \ if (debug >= (level)) { \
if ((level) == 1) \ if ((level) == 1) \
dev_err(&cam->dev, fmt "\n", ## args); \ dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) == 2) \ else if ((level) == 2) \
dev_info(&cam->dev, fmt "\n", ## args); \ dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
else if ((level) >= 3) \ else if ((level) >= 3) \
dev_info(&cam->dev, "[%s:%d] " fmt "\n", \ dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
__FUNCTION__, __LINE__ , ## args); \ __FUNCTION__, __LINE__ , ## args); \
} \ } \
} while (0) } while (0)
# define V4LDBG(level, name, cmd) \
do { \
if (debug >= (level)) \
v4l_print_ioctl(name, cmd); \
} while (0)
# define KDBG(level, fmt, args...) \ # define KDBG(level, fmt, args...) \
do { \ do { \
if (debug >= (level)) { \ if (debug >= (level)) { \
...@@ -193,8 +189,9 @@ do { \ ...@@ -193,8 +189,9 @@ do { \
} \ } \
} while (0) } while (0)
#else #else
# define KDBG(level, fmt, args...) do {;} while(0)
# define DBG(level, fmt, args...) do {;} while(0) # define DBG(level, fmt, args...) do {;} while(0)
# define V4LDBG(level, name, cmd) do {;} while(0)
# define KDBG(level, fmt, args...) do {;} while(0)
#endif #endif
#undef PDBG #undef PDBG
......
...@@ -45,6 +45,15 @@ ...@@ -45,6 +45,15 @@
/*****************************************************************************/ /*****************************************************************************/
#define SN9C102_MODULE_NAME "V4L2 driver for SN9C10x PC Camera Controllers"
#define SN9C102_MODULE_AUTHOR "(C) 2004-2006 Luca Risolia"
#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
#define SN9C102_MODULE_LICENSE "GPL"
#define SN9C102_MODULE_VERSION "1:1.26"
#define SN9C102_MODULE_VERSION_CODE KERNEL_VERSION(1, 0, 26)
/*****************************************************************************/
MODULE_DEVICE_TABLE(usb, sn9c102_id_table); MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL); MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
...@@ -115,50 +124,6 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = { ...@@ -115,50 +124,6 @@ static sn9c102_eof_header_t sn9c102_eof_header[] = {
/*****************************************************************************/ /*****************************************************************************/
static void* rvmalloc(size_t size)
{
void* mem;
unsigned long adr;
size = PAGE_ALIGN(size);
mem = vmalloc_32((unsigned long)size);
if (!mem)
return NULL;
memset(mem, 0, size);
adr = (unsigned long)mem;
while (size > 0) {
SetPageReserved(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
size -= PAGE_SIZE;
}
return mem;
}
static void rvfree(void* mem, size_t size)
{
unsigned long adr;
if (!mem)
return;
size = PAGE_ALIGN(size);
adr = (unsigned long)mem;
while (size > 0) {
ClearPageReserved(vmalloc_to_page((void *)adr));
adr += PAGE_SIZE;
size -= PAGE_SIZE;
}
vfree(mem);
}
static u32 static u32
sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
enum sn9c102_io_method io) enum sn9c102_io_method io)
...@@ -177,7 +142,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, ...@@ -177,7 +142,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
cam->nbuffers = count; cam->nbuffers = count;
while (cam->nbuffers > 0) { while (cam->nbuffers > 0) {
if ((buff = rvmalloc(cam->nbuffers * PAGE_ALIGN(imagesize)))) if ((buff = vmalloc_32(cam->nbuffers * PAGE_ALIGN(imagesize))))
break; break;
cam->nbuffers--; cam->nbuffers--;
} }
...@@ -201,8 +166,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count, ...@@ -201,8 +166,7 @@ sn9c102_request_buffers(struct sn9c102_device* cam, u32 count,
static void sn9c102_release_buffers(struct sn9c102_device* cam) static void sn9c102_release_buffers(struct sn9c102_device* cam)
{ {
if (cam->nbuffers) { if (cam->nbuffers) {
rvfree(cam->frame[0].bufmem, vfree(cam->frame[0].bufmem);
cam->nbuffers * PAGE_ALIGN(cam->frame[0].buf.length));
cam->nbuffers = 0; cam->nbuffers = 0;
} }
cam->frame_current = NULL; cam->frame_current = NULL;
...@@ -745,7 +709,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam) ...@@ -745,7 +709,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
int err = 0; int err = 0;
for (i = 0; i < SN9C102_URBS; i++) { for (i = 0; i < SN9C102_URBS; i++) {
cam->transfer_buffer[i] = kmalloc(SN9C102_ISO_PACKETS * psz, cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
GFP_KERNEL); GFP_KERNEL);
if (!cam->transfer_buffer[i]) { if (!cam->transfer_buffer[i]) {
err = -ENOMEM; err = -ENOMEM;
...@@ -865,6 +829,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam) ...@@ -865,6 +829,7 @@ static int sn9c102_stream_interrupt(struct sn9c102_device* cam)
/*****************************************************************************/ /*****************************************************************************/
#ifdef CONFIG_VIDEO_ADV_DEBUG
static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count) static u8 sn9c102_strtou8(const char* buff, size_t len, ssize_t* count)
{ {
char str[5]; char str[5];
...@@ -1289,6 +1254,7 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam) ...@@ -1289,6 +1254,7 @@ static void sn9c102_create_sysfs(struct sn9c102_device* cam)
video_device_create_file(v4ldev, &class_device_attr_i2c_val); video_device_create_file(v4ldev, &class_device_attr_i2c_val);
} }
} }
#endif /* CONFIG_VIDEO_ADV_DEBUG */
/*****************************************************************************/ /*****************************************************************************/
...@@ -1754,9 +1720,8 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) ...@@ -1754,9 +1720,8 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
{ {
struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp)); struct sn9c102_device* cam = video_get_drvdata(video_devdata(filp));
unsigned long size = vma->vm_end - vma->vm_start, unsigned long size = vma->vm_end - vma->vm_start,
start = vma->vm_start, start = vma->vm_start;
pos, void *pos;
page;
u32 i; u32 i;
if (down_interruptible(&cam->fileop_sem)) if (down_interruptible(&cam->fileop_sem))
...@@ -1790,15 +1755,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma) ...@@ -1790,15 +1755,12 @@ static int sn9c102_mmap(struct file* filp, struct vm_area_struct *vma)
return -EINVAL; return -EINVAL;
} }
/* VM_IO is eventually going to replace PageReserved altogether */
vma->vm_flags |= VM_IO; vma->vm_flags |= VM_IO;
vma->vm_flags |= VM_RESERVED; /* avoid to swap out this VMA */ vma->vm_flags |= VM_RESERVED;
pos = (unsigned long)cam->frame[i].bufmem; pos = cam->frame[i].bufmem;
while (size > 0) { /* size is page-aligned */ while (size > 0) { /* size is page-aligned */
page = vmalloc_to_pfn((void *)pos); if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
if (remap_pfn_range(vma, start, page, PAGE_SIZE,
vma->vm_page_prot)) {
up(&cam->fileop_sem); up(&cam->fileop_sem);
return -EAGAIN; return -EAGAIN;
} }
...@@ -1831,7 +1793,8 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg) ...@@ -1831,7 +1793,8 @@ sn9c102_vidioc_querycap(struct sn9c102_device* cam, void __user * arg)
strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card)); strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0) if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
strlcpy(cap.bus_info, cam->dev.bus_id, sizeof(cap.bus_info)); strlcpy(cap.bus_info, cam->usbdev->dev.bus_id,
sizeof(cap.bus_info));
if (copy_to_user(arg, &cap, sizeof(cap))) if (copy_to_user(arg, &cap, sizeof(cap)))
return -EFAULT; return -EFAULT;
...@@ -1852,7 +1815,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg) ...@@ -1852,7 +1815,7 @@ sn9c102_vidioc_enuminput(struct sn9c102_device* cam, void __user * arg)
return -EINVAL; return -EINVAL;
memset(&i, 0, sizeof(i)); memset(&i, 0, sizeof(i));
strcpy(i.name, "USB"); strcpy(i.name, "Camera");
if (copy_to_user(arg, &i, sizeof(i))) if (copy_to_user(arg, &i, sizeof(i)))
return -EFAULT; return -EFAULT;
...@@ -2708,6 +2671,8 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp, ...@@ -2708,6 +2671,8 @@ static int sn9c102_ioctl(struct inode* inode, struct file* filp,
return -EIO; return -EIO;
} }
V4LDBG(3, "sn9c102", cmd);
err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg); err = sn9c102_ioctl_v4l2(inode, filp, cmd, (void __user *)arg);
up(&cam->fileop_sem); up(&cam->fileop_sem);
...@@ -2740,13 +2705,12 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2740,13 +2705,12 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
unsigned int i; unsigned int i;
int err = 0, r; int err = 0, r;
if (!(cam = kmalloc(sizeof(struct sn9c102_device), GFP_KERNEL))) if (!(cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL)))
return -ENOMEM; return -ENOMEM;
cam->usbdev = udev; cam->usbdev = udev;
memcpy(&cam->dev, &udev->dev, sizeof(struct device));
if (!(cam->control_buffer = kmalloc(8, GFP_KERNEL))) { if (!(cam->control_buffer = kzalloc(8, GFP_KERNEL))) {
DBG(1, "kmalloc() failed"); DBG(1, "kmalloc() failed");
err = -ENOMEM; err = -ENOMEM;
goto fail; goto fail;
...@@ -2806,7 +2770,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2806,7 +2770,7 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
strcpy(cam->v4ldev->name, "SN9C10x PC Camera"); strcpy(cam->v4ldev->name, "SN9C10x PC Camera");
cam->v4ldev->owner = THIS_MODULE; cam->v4ldev->owner = THIS_MODULE;
cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES; cam->v4ldev->type = VID_TYPE_CAPTURE | VID_TYPE_SCALES;
cam->v4ldev->hardware = VID_HARDWARE_SN9C102; cam->v4ldev->hardware = 0;
cam->v4ldev->fops = &sn9c102_fops; cam->v4ldev->fops = &sn9c102_fops;
cam->v4ldev->minor = video_nr[dev_nr]; cam->v4ldev->minor = video_nr[dev_nr];
cam->v4ldev->release = video_device_release; cam->v4ldev->release = video_device_release;
...@@ -2832,8 +2796,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id) ...@@ -2832,8 +2796,10 @@ sn9c102_usb_probe(struct usb_interface* intf, const struct usb_device_id* id)
dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0; dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
#ifdef CONFIG_VIDEO_ADV_DEBUG
sn9c102_create_sysfs(cam); sn9c102_create_sysfs(cam);
DBG(2, "Optional device control through 'sysfs' interface ready"); DBG(2, "Optional device control through 'sysfs' interface ready");
#endif
usb_set_intfdata(intf, cam); usb_set_intfdata(intf, cam);
......
...@@ -196,10 +196,11 @@ extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index); ...@@ -196,10 +196,11 @@ extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
/* /*
NOTE: there are no exported debugging functions. To uniform the output you NOTE: there are no exported debugging functions. To uniform the output you
must use the dev_info()/dev_warn()/dev_err() macros defined in device.h, must use the dev_info()/dev_warn()/dev_err() macros defined in device.h,
already included here, the argument being the struct device 'dev' of the already included here, the argument being the struct device '&usbdev->dev'
sensor structure. Do NOT use these macros before the sensor is attached or of the sensor structure. Do NOT use these macros before the sensor is
the kernel will crash! However, you should not need to notify the user about attached or the kernel will crash! However, you should not need to notify
common errors or other messages, since this is done by the master module. the user about common errors or other messages, since this is done by the
master module.
*/ */
/*****************************************************************************/ /*****************************************************************************/
...@@ -358,13 +359,6 @@ struct sn9c102_sensor { ...@@ -358,13 +359,6 @@ struct sn9c102_sensor {
error code without rolling back. error code without rolling back.
*/ */
const struct device* dev;
/*
This is the argument for dev_err(), dev_info() and dev_warn(). It
is used for debugging purposes. You must not access the struct
before the sensor is attached.
*/
const struct usb_device* usbdev; const struct usb_device* usbdev;
/* /*
Points to the usb_device struct after the sensor is attached. Points to the usb_device struct after the sensor is attached.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment