[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: Luca Risolia <luca.risolia@studio.unibo.it> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
e988fc8a56
commit
cd6fcc555f
@@ -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
|
|||||||
|
|
||||||
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 @@
|
|||||||
|
|
||||||
#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 @@
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
#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);
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 { \
|
|||||||
} \
|
} \
|
||||||
} 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 @@
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#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[] = {
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
#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)
|
|||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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,
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
|||||||
/*
|
/*
|
||||||
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 {
|
|||||||
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.
|
||||||
|
Reference in New Issue
Block a user