diff options
-rw-r--r-- | drivers/firewire/fw-cdev.c | 17 | ||||
-rw-r--r-- | include/linux/firewire-cdev.h | 14 |
2 files changed, 24 insertions, 7 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c index 3ab3585d3601..5d402d63799f 100644 --- a/drivers/firewire/fw-cdev.c +++ b/drivers/firewire/fw-cdev.c | |||
@@ -677,12 +677,21 @@ static int ioctl_create_iso_context(struct client *client, void *buffer) | |||
677 | return 0; | 677 | return 0; |
678 | } | 678 | } |
679 | 679 | ||
680 | /* Macros for decoding the iso packet control header. */ | ||
681 | #define GET_PAYLOAD_LENGTH(v) ((v) & 0xffff) | ||
682 | #define GET_INTERRUPT(v) (((v) >> 16) & 0x01) | ||
683 | #define GET_SKIP(v) (((v) >> 17) & 0x01) | ||
684 | #define GET_TAG(v) (((v) >> 18) & 0x02) | ||
685 | #define GET_SY(v) (((v) >> 20) & 0x04) | ||
686 | #define GET_HEADER_LENGTH(v) (((v) >> 24) & 0xff) | ||
687 | |||
680 | static int ioctl_queue_iso(struct client *client, void *buffer) | 688 | static int ioctl_queue_iso(struct client *client, void *buffer) |
681 | { | 689 | { |
682 | struct fw_cdev_queue_iso *request = buffer; | 690 | struct fw_cdev_queue_iso *request = buffer; |
683 | struct fw_cdev_iso_packet __user *p, *end, *next; | 691 | struct fw_cdev_iso_packet __user *p, *end, *next; |
684 | struct fw_iso_context *ctx = client->iso_context; | 692 | struct fw_iso_context *ctx = client->iso_context; |
685 | unsigned long payload, buffer_end, header_length; | 693 | unsigned long payload, buffer_end, header_length; |
694 | u32 control; | ||
686 | int count; | 695 | int count; |
687 | struct { | 696 | struct { |
688 | struct fw_iso_packet packet; | 697 | struct fw_iso_packet packet; |
@@ -717,8 +726,14 @@ static int ioctl_queue_iso(struct client *client, void *buffer) | |||
717 | end = (void __user *)p + request->size; | 726 | end = (void __user *)p + request->size; |
718 | count = 0; | 727 | count = 0; |
719 | while (p < end) { | 728 | while (p < end) { |
720 | if (__copy_from_user(&u.packet, p, sizeof(*p))) | 729 | if (get_user(control, &p->control)) |
721 | return -EFAULT; | 730 | return -EFAULT; |
731 | u.packet.payload_length = GET_PAYLOAD_LENGTH(control); | ||
732 | u.packet.interrupt = GET_INTERRUPT(control); | ||
733 | u.packet.skip = GET_SKIP(control); | ||
734 | u.packet.tag = GET_TAG(control); | ||
735 | u.packet.sy = GET_SY(control); | ||
736 | u.packet.header_length = GET_HEADER_LENGTH(control); | ||
722 | 737 | ||
723 | if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { | 738 | if (ctx->type == FW_ISO_CONTEXT_TRANSMIT) { |
724 | header_length = u.packet.header_length; | 739 | header_length = u.packet.header_length; |
diff --git a/include/linux/firewire-cdev.h b/include/linux/firewire-cdev.h index d4455eb2ae35..efbe1fda1a22 100644 --- a/include/linux/firewire-cdev.h +++ b/include/linux/firewire-cdev.h | |||
@@ -198,13 +198,15 @@ struct fw_cdev_create_iso_context { | |||
198 | __u32 handle; | 198 | __u32 handle; |
199 | }; | 199 | }; |
200 | 200 | ||
201 | #define FW_CDEV_ISO_PAYLOAD_LENGTH(v) (v) | ||
202 | #define FW_CDEV_ISO_INTERRUPT (1 << 16) | ||
203 | #define FW_CDEV_ISO_SKIP (1 << 17) | ||
204 | #define FW_CDEV_ISO_TAG(v) ((v) << 18) | ||
205 | #define FW_CDEV_ISO_SY(v) ((v) << 20) | ||
206 | #define FW_CDEV_ISO_HEADER_LENGTH(v) ((v) << 24) | ||
207 | |||
201 | struct fw_cdev_iso_packet { | 208 | struct fw_cdev_iso_packet { |
202 | __u16 payload_length; /* Length of indirect payload. */ | 209 | __u32 control; |
203 | __u32 interrupt : 1; /* Generate interrupt on this packet */ | ||
204 | __u32 skip : 1; /* Set to not send packet at all. */ | ||
205 | __u32 tag : 2; | ||
206 | __u32 sy : 4; | ||
207 | __u32 header_length : 8; /* Length of immediate header. */ | ||
208 | __u32 header[0]; | 210 | __u32 header[0]; |
209 | }; | 211 | }; |
210 | 212 | ||