summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/media/video/saa5246a.c97
1 files changed, 50 insertions, 47 deletions
diff --git a/drivers/media/video/saa5246a.c b/drivers/media/video/saa5246a.c
index 7226ef56f1e3..c2fb64d57ca7 100644
--- a/drivers/media/video/saa5246a.c
+++ b/drivers/media/video/saa5246a.c
@@ -485,73 +485,76 @@ static inline int saa5246a_get_status(struct saa5246a_device *t,
static inline int saa5246a_get_page(struct saa5246a_device *t,
vtx_pagereq_t *req)
{
- int start, end;
+ int start, end, size;
+ char *buf;
+ int err;
if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS ||
req->start < 0 || req->start > req->end || req->end >= VTX_PAGESIZE)
return -EINVAL;
- /* Read "normal" part of page */
- end = min(req->end, VTX_PAGESIZE - 1);
- if (i2c_senddata(t, SAA5246A_REGISTER_R8,
- req->pgbuf |
- R8_DO_NOT_CLEAR_MEMORY,
+ buf = kmalloc(VTX_PAGESIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- ROW(req->start),
+ /* Read "normal" part of page */
+ err = -EIO;
- COLUMN(req->start),
+ end = min(req->end, VTX_PAGESIZE - 1);
+ if (i2c_senddata(t, SAA5246A_REGISTER_R8,
+ req->pgbuf | R8_DO_NOT_CLEAR_MEMORY,
+ ROW(req->start), COLUMN(req->start), COMMAND_END))
+ goto out;
+ if (i2c_getdata(t, end - req->start + 1, buf))
+ goto out;
+ err = -EFAULT;
+ if (copy_to_user(req->buffer, buf, end - req->start + 1))
+ goto out;
- COMMAND_END) ||
- i2c_getdata(t, end - req->start + 1, req->buffer))
- {
- return -EIO;
- }
/* Always get the time from buffer 4, since this stupid SAA5246A only
* updates the currently displayed buffer...
*/
- if (REQ_CONTAINS_TIME(req))
- {
+ if (REQ_CONTAINS_TIME(req)) {
start = max(req->start, POS_TIME_START);
end = min(req->end, POS_TIME_END);
+ size = end - start + 1;
+ err = -EINVAL;
+ if (size < 0)
+ goto out;
+ err = -EIO;
if (i2c_senddata(t, SAA5246A_REGISTER_R8,
-
- R8_ACTIVE_CHAPTER_4 |
- R8_DO_NOT_CLEAR_MEMORY,
-
- R9_CURSER_ROW_0,
-
- start,
-
- COMMAND_END) ||
- i2c_getdata(t, end - start + 1,
- req->buffer + start - req->start))
- {
- return -EIO;
- }
+ R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,
+ R9_CURSER_ROW_0, start, COMMAND_END))
+ goto out;
+ if (i2c_getdata(t, size, buf))
+ goto out;
+ err = -EFAULT;
+ if (copy_to_user(req->buffer + start - req->start, buf, size))
+ goto out;
}
/* Insert the header from buffer 4 only, if acquisition circuit is still searching for a page */
- if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf])
- {
+ if (REQ_CONTAINS_HEADER(req) && t->is_searching[req->pgbuf]) {
start = max(req->start, POS_HEADER_START);
end = min(req->end, POS_HEADER_END);
+ size = end - start + 1;
+ err = -EINVAL;
+ if (size < 0)
+ goto out;
+ err = -EIO;
if (i2c_senddata(t, SAA5246A_REGISTER_R8,
-
- R8_ACTIVE_CHAPTER_4 |
- R8_DO_NOT_CLEAR_MEMORY,
-
- R9_CURSER_ROW_0,
-
- start,
-
- COMMAND_END) ||
- i2c_getdata(t, end - start + 1,
- req->buffer + start - req->start))
- {
- return -EIO;
- }
+ R8_ACTIVE_CHAPTER_4 | R8_DO_NOT_CLEAR_MEMORY,
+ R9_CURSER_ROW_0, start, COMMAND_END))
+ goto out;
+ if (i2c_getdata(t, end - start + 1, buf))
+ goto out;
+ err = -EFAULT;
+ if (copy_to_user(req->buffer + start - req->start, buf, size))
+ goto out;
}
-
- return 0;
+ err = 0;
+out:
+ kfree(buf);
+ return err;
}
/* Stops the acquisition circuit given in dau_no. The page buffer associated