diff options
-rw-r--r-- | drivers/media/video/ivtv/ivtv-fileops.c | 3 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.c | 109 | ||||
-rw-r--r-- | drivers/media/video/ivtv/ivtv-vbi.h | 4 |
3 files changed, 78 insertions, 38 deletions
diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index d727485da886..4f46b0070806 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -570,7 +570,8 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c int elems = count / sizeof(struct v4l2_sliced_vbi_data); set_bit(IVTV_F_S_APPL_IO, &s->s_flags); - ivtv_write_vbi(itv, (const struct v4l2_sliced_vbi_data *)user_buf, elems); + ivtv_write_vbi_from_user(itv, + (const struct v4l2_sliced_vbi_data __user *)user_buf, elems); return elems * sizeof(struct v4l2_sliced_vbi_data); } diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index e1c347e5ebd8..7275f2d6597e 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -92,54 +92,91 @@ static int odd_parity(u8 c) return c & 1; } -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t cnt) +static void ivtv_write_vbi_line(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *d, + struct vbi_cc *cc, int *found_cc) { struct vbi_info *vi = &itv->vbi; - struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; - int found_cc = 0; - size_t i; - - for (i = 0; i < cnt; i++) { - const struct v4l2_sliced_vbi_data *d = sliced + i; - if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { - if (d->field) { - cc.even[0] = d->data[0]; - cc.even[1] = d->data[1]; - } else { - cc.odd[0] = d->data[0]; - cc.odd[1] = d->data[1]; - } - found_cc = 1; + if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) { + if (d->field) { + cc->even[0] = d->data[0]; + cc->even[1] = d->data[1]; + } else { + cc->odd[0] = d->data[0]; + cc->odd[1] = d->data[1]; } - else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { - struct vbi_vps vps; - - vps.data[0] = d->data[2]; - vps.data[1] = d->data[8]; - vps.data[2] = d->data[9]; - vps.data[3] = d->data[10]; - vps.data[4] = d->data[11]; - if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { - vi->vps_payload = vps; - set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); - } + *found_cc = 1; + } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) { + struct vbi_vps vps; + + vps.data[0] = d->data[2]; + vps.data[1] = d->data[8]; + vps.data[2] = d->data[9]; + vps.data[3] = d->data[10]; + vps.data[4] = d->data[11]; + if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) { + vi->vps_payload = vps; + set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags); } - else if (d->id == V4L2_SLICED_WSS_625 && d->line == 23 && d->field == 0) { - int wss = d->data[0] | d->data[1] << 8; + } else if (d->id == V4L2_SLICED_WSS_625 && + d->line == 23 && d->field == 0) { + int wss = d->data[0] | d->data[1] << 8; - if (vi->wss_payload != wss) { - vi->wss_payload = wss; - set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); - } + if (vi->wss_payload != wss) { + vi->wss_payload = wss; + set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags); } } - if (found_cc && vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { - vi->cc_payload[vi->cc_payload_idx++] = cc; +} + +static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc) +{ + struct vbi_info *vi = &itv->vbi; + + if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) { + memcpy(&vi->cc_payload[vi->cc_payload_idx], cc, + sizeof(struct vbi_cc)); + vi->cc_payload_idx++; set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags); } } +static void ivtv_write_vbi(struct ivtv *itv, + const struct v4l2_sliced_vbi_data *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + + for (i = 0; i < cnt; i++) + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + +void ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t cnt) +{ + struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } }; + int found_cc = 0; + size_t i; + struct v4l2_sliced_vbi_data d; + + for (i = 0; i < cnt; i++) { + if (copy_from_user(&d, sliced + i, + sizeof(struct v4l2_sliced_vbi_data))) + break; + ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc); + } + + if (found_cc) + ivtv_write_vbi_cc_lines(itv, &cc); +} + static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) { int line = 0; diff --git a/drivers/media/video/ivtv/ivtv-vbi.h b/drivers/media/video/ivtv/ivtv-vbi.h index 970567b9194d..eda38d0ad7ce 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.h +++ b/drivers/media/video/ivtv/ivtv-vbi.h @@ -20,7 +20,9 @@ #ifndef IVTV_VBI_H #define IVTV_VBI_H -void ivtv_write_vbi(struct ivtv *itv, const struct v4l2_sliced_vbi_data *sliced, size_t count); +void ivtv_write_vbi_from_user(struct ivtv *itv, + const struct v4l2_sliced_vbi_data __user *sliced, + size_t count); void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, u64 pts_stamp, int streamtype); int ivtv_used_line(struct ivtv *itv, int line, int field); |