diff options
author | Laurent Pinchart <laurent.pinchart@skynet.be> | 2008-07-31 16:11:12 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-08-06 05:57:37 -0400 |
commit | 04793dd041bbb88a39b768b714c725de2c339b51 (patch) | |
tree | 2d801aeb2d3fe12f86ed493ed9b541ad2873c52b /drivers/media/video/uvc | |
parent | 835f09c6594aa98cbfae05c5466a81fda3081d2c (diff) |
V4L/DVB (8617): uvcvideo: don't use stack-based buffers for USB transfers.
Data buffers on the stack are not allowed for USB I/O. Use dynamically
allocated buffers instead.
Signed-off-by: Bruce Schmid <duck@freescale.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@skynet.be>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/uvc')
-rw-r--r-- | drivers/media/video/uvc/uvc_ctrl.c | 33 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_video.c | 33 |
2 files changed, 43 insertions, 23 deletions
diff --git a/drivers/media/video/uvc/uvc_ctrl.c b/drivers/media/video/uvc/uvc_ctrl.c index 626f4ad7e876..6ef3e5297de8 100644 --- a/drivers/media/video/uvc/uvc_ctrl.c +++ b/drivers/media/video/uvc/uvc_ctrl.c | |||
@@ -585,13 +585,17 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | |||
585 | struct uvc_control_mapping *mapping; | 585 | struct uvc_control_mapping *mapping; |
586 | struct uvc_menu_info *menu; | 586 | struct uvc_menu_info *menu; |
587 | unsigned int i; | 587 | unsigned int i; |
588 | __u8 data[8]; | 588 | __u8 *data; |
589 | int ret; | 589 | int ret; |
590 | 590 | ||
591 | ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); | 591 | ctrl = uvc_find_control(video, v4l2_ctrl->id, &mapping); |
592 | if (ctrl == NULL) | 592 | if (ctrl == NULL) |
593 | return -EINVAL; | 593 | return -EINVAL; |
594 | 594 | ||
595 | data = kmalloc(8, GFP_KERNEL); | ||
596 | if (data == NULL) | ||
597 | return -ENOMEM; | ||
598 | |||
595 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); | 599 | memset(v4l2_ctrl, 0, sizeof *v4l2_ctrl); |
596 | v4l2_ctrl->id = mapping->id; | 600 | v4l2_ctrl->id = mapping->id; |
597 | v4l2_ctrl->type = mapping->v4l2_type; | 601 | v4l2_ctrl->type = mapping->v4l2_type; |
@@ -604,8 +608,8 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | |||
604 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { | 608 | if (ctrl->info->flags & UVC_CONTROL_GET_DEF) { |
605 | if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, | 609 | if ((ret = uvc_query_ctrl(video->dev, GET_DEF, ctrl->entity->id, |
606 | video->dev->intfnum, ctrl->info->selector, | 610 | video->dev->intfnum, ctrl->info->selector, |
607 | &data, ctrl->info->size)) < 0) | 611 | data, ctrl->info->size)) < 0) |
608 | return ret; | 612 | goto out; |
609 | v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); | 613 | v4l2_ctrl->default_value = uvc_get_le_value(data, mapping); |
610 | } | 614 | } |
611 | 615 | ||
@@ -623,13 +627,15 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | |||
623 | } | 627 | } |
624 | } | 628 | } |
625 | 629 | ||
626 | return 0; | 630 | ret = 0; |
631 | goto out; | ||
627 | 632 | ||
628 | case V4L2_CTRL_TYPE_BOOLEAN: | 633 | case V4L2_CTRL_TYPE_BOOLEAN: |
629 | v4l2_ctrl->minimum = 0; | 634 | v4l2_ctrl->minimum = 0; |
630 | v4l2_ctrl->maximum = 1; | 635 | v4l2_ctrl->maximum = 1; |
631 | v4l2_ctrl->step = 1; | 636 | v4l2_ctrl->step = 1; |
632 | return 0; | 637 | ret = 0; |
638 | goto out; | ||
633 | 639 | ||
634 | default: | 640 | default: |
635 | break; | 641 | break; |
@@ -638,26 +644,29 @@ int uvc_query_v4l2_ctrl(struct uvc_video_device *video, | |||
638 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { | 644 | if (ctrl->info->flags & UVC_CONTROL_GET_MIN) { |
639 | if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, | 645 | if ((ret = uvc_query_ctrl(video->dev, GET_MIN, ctrl->entity->id, |
640 | video->dev->intfnum, ctrl->info->selector, | 646 | video->dev->intfnum, ctrl->info->selector, |
641 | &data, ctrl->info->size)) < 0) | 647 | data, ctrl->info->size)) < 0) |
642 | return ret; | 648 | goto out; |
643 | v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); | 649 | v4l2_ctrl->minimum = uvc_get_le_value(data, mapping); |
644 | } | 650 | } |
645 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { | 651 | if (ctrl->info->flags & UVC_CONTROL_GET_MAX) { |
646 | if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, | 652 | if ((ret = uvc_query_ctrl(video->dev, GET_MAX, ctrl->entity->id, |
647 | video->dev->intfnum, ctrl->info->selector, | 653 | video->dev->intfnum, ctrl->info->selector, |
648 | &data, ctrl->info->size)) < 0) | 654 | data, ctrl->info->size)) < 0) |
649 | return ret; | 655 | goto out; |
650 | v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); | 656 | v4l2_ctrl->maximum = uvc_get_le_value(data, mapping); |
651 | } | 657 | } |
652 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { | 658 | if (ctrl->info->flags & UVC_CONTROL_GET_RES) { |
653 | if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, | 659 | if ((ret = uvc_query_ctrl(video->dev, GET_RES, ctrl->entity->id, |
654 | video->dev->intfnum, ctrl->info->selector, | 660 | video->dev->intfnum, ctrl->info->selector, |
655 | &data, ctrl->info->size)) < 0) | 661 | data, ctrl->info->size)) < 0) |
656 | return ret; | 662 | goto out; |
657 | v4l2_ctrl->step = uvc_get_le_value(data, mapping); | 663 | v4l2_ctrl->step = uvc_get_le_value(data, mapping); |
658 | } | 664 | } |
659 | 665 | ||
660 | return 0; | 666 | ret = 0; |
667 | out: | ||
668 | kfree(data); | ||
669 | return ret; | ||
661 | } | 670 | } |
662 | 671 | ||
663 | 672 | ||
diff --git a/drivers/media/video/uvc/uvc_video.c b/drivers/media/video/uvc/uvc_video.c index ad63794fda77..6854ac78a161 100644 --- a/drivers/media/video/uvc/uvc_video.c +++ b/drivers/media/video/uvc/uvc_video.c | |||
@@ -90,17 +90,20 @@ static void uvc_fixup_buffer_size(struct uvc_video_device *video, | |||
90 | static int uvc_get_video_ctrl(struct uvc_video_device *video, | 90 | static int uvc_get_video_ctrl(struct uvc_video_device *video, |
91 | struct uvc_streaming_control *ctrl, int probe, __u8 query) | 91 | struct uvc_streaming_control *ctrl, int probe, __u8 query) |
92 | { | 92 | { |
93 | __u8 data[34]; | 93 | __u8 *data; |
94 | __u8 size; | 94 | __u16 size; |
95 | int ret; | 95 | int ret; |
96 | 96 | ||
97 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | 97 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; |
98 | data = kmalloc(size, GFP_KERNEL); | ||
99 | if (data == NULL) | ||
100 | return -ENOMEM; | ||
101 | |||
98 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, | 102 | ret = __uvc_query_ctrl(video->dev, query, 0, video->streaming->intfnum, |
99 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | 103 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, |
100 | UVC_CTRL_STREAMING_TIMEOUT); | 104 | UVC_CTRL_STREAMING_TIMEOUT); |
101 | |||
102 | if (ret < 0) | 105 | if (ret < 0) |
103 | return ret; | 106 | goto out; |
104 | 107 | ||
105 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); | 108 | ctrl->bmHint = le16_to_cpup((__le16 *)&data[0]); |
106 | ctrl->bFormatIndex = data[2]; | 109 | ctrl->bFormatIndex = data[2]; |
@@ -136,17 +139,22 @@ static int uvc_get_video_ctrl(struct uvc_video_device *video, | |||
136 | */ | 139 | */ |
137 | uvc_fixup_buffer_size(video, ctrl); | 140 | uvc_fixup_buffer_size(video, ctrl); |
138 | 141 | ||
139 | return 0; | 142 | out: |
143 | kfree(data); | ||
144 | return ret; | ||
140 | } | 145 | } |
141 | 146 | ||
142 | int uvc_set_video_ctrl(struct uvc_video_device *video, | 147 | int uvc_set_video_ctrl(struct uvc_video_device *video, |
143 | struct uvc_streaming_control *ctrl, int probe) | 148 | struct uvc_streaming_control *ctrl, int probe) |
144 | { | 149 | { |
145 | __u8 data[34]; | 150 | __u8 *data; |
146 | __u8 size; | 151 | __u16 size; |
152 | int ret; | ||
147 | 153 | ||
148 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; | 154 | size = video->dev->uvc_version >= 0x0110 ? 34 : 26; |
149 | memset(data, 0, sizeof data); | 155 | data = kzalloc(size, GFP_KERNEL); |
156 | if (data == NULL) | ||
157 | return -ENOMEM; | ||
150 | 158 | ||
151 | *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); | 159 | *(__le16 *)&data[0] = cpu_to_le16(ctrl->bmHint); |
152 | data[2] = ctrl->bFormatIndex; | 160 | data[2] = ctrl->bFormatIndex; |
@@ -174,10 +182,13 @@ int uvc_set_video_ctrl(struct uvc_video_device *video, | |||
174 | data[33] = ctrl->bMaxVersion; | 182 | data[33] = ctrl->bMaxVersion; |
175 | } | 183 | } |
176 | 184 | ||
177 | return __uvc_query_ctrl(video->dev, SET_CUR, 0, | 185 | ret = __uvc_query_ctrl(video->dev, SET_CUR, 0, |
178 | video->streaming->intfnum, | 186 | video->streaming->intfnum, |
179 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, &data, size, | 187 | probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size, |
180 | UVC_CTRL_STREAMING_TIMEOUT); | 188 | UVC_CTRL_STREAMING_TIMEOUT); |
189 | |||
190 | kfree(data); | ||
191 | return ret; | ||
181 | } | 192 | } |
182 | 193 | ||
183 | int uvc_probe_video(struct uvc_video_device *video, | 194 | int uvc_probe_video(struct uvc_video_device *video, |