diff options
author | Kristian Høgsberg <krh@redhat.com> | 2007-02-16 17:34:40 -0500 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2007-03-09 16:02:58 -0500 |
commit | 295e3feb92e5073ec32a3c626302d4b92c4c8a95 (patch) | |
tree | 58c581080526c4b27401d3c2f4e52595d78cc4e8 /drivers/firewire/fw-device-cdev.c | |
parent | 30200739e612932739cc34baf588b39bacc2f427 (diff) |
firewire: Implement basic isochronous receive functionality.
Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/firewire/fw-device-cdev.c')
-rw-r--r-- | drivers/firewire/fw-device-cdev.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/drivers/firewire/fw-device-cdev.c b/drivers/firewire/fw-device-cdev.c index 6284375c6390..1101ccd9b9c1 100644 --- a/drivers/firewire/fw-device-cdev.c +++ b/drivers/firewire/fw-device-cdev.c | |||
@@ -406,8 +406,12 @@ static int ioctl_create_iso_context(struct client *client, void __user *arg) | |||
406 | if (copy_from_user(&request, arg, sizeof request)) | 406 | if (copy_from_user(&request, arg, sizeof request)) |
407 | return -EFAULT; | 407 | return -EFAULT; |
408 | 408 | ||
409 | if (request.type > FW_ISO_CONTEXT_RECEIVE) | ||
410 | return -EINVAL; | ||
411 | |||
409 | client->iso_context = fw_iso_context_create(client->device->card, | 412 | client->iso_context = fw_iso_context_create(client->device->card, |
410 | FW_ISO_CONTEXT_TRANSMIT, | 413 | request.type, |
414 | request.header_size, | ||
411 | iso_callback, client); | 415 | iso_callback, client); |
412 | if (IS_ERR(client->iso_context)) | 416 | if (IS_ERR(client->iso_context)) |
413 | return PTR_ERR(client->iso_context); | 417 | return PTR_ERR(client->iso_context); |
@@ -419,7 +423,7 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
419 | { | 423 | { |
420 | struct fw_cdev_queue_iso request; | 424 | struct fw_cdev_queue_iso request; |
421 | struct fw_cdev_iso_packet __user *p, *end, *next; | 425 | struct fw_cdev_iso_packet __user *p, *end, *next; |
422 | unsigned long payload, payload_end; | 426 | unsigned long payload, payload_end, header_length; |
423 | int count; | 427 | int count; |
424 | struct { | 428 | struct { |
425 | struct fw_iso_packet packet; | 429 | struct fw_iso_packet packet; |
@@ -456,12 +460,23 @@ static int ioctl_queue_iso(struct client *client, void __user *arg) | |||
456 | while (p < end) { | 460 | while (p < end) { |
457 | if (__copy_from_user(&u.packet, p, sizeof *p)) | 461 | if (__copy_from_user(&u.packet, p, sizeof *p)) |
458 | return -EFAULT; | 462 | return -EFAULT; |
463 | |||
464 | if (client->iso_context->type == FW_ISO_CONTEXT_TRANSMIT) { | ||
465 | header_length = u.packet.header_length; | ||
466 | } else { | ||
467 | /* We require that header_length is a multiple of | ||
468 | * the fixed header size, ctx->header_size */ | ||
469 | if (u.packet.header_length % client->iso_context->header_size != 0) | ||
470 | return -EINVAL; | ||
471 | header_length = 0; | ||
472 | } | ||
473 | |||
459 | next = (struct fw_cdev_iso_packet __user *) | 474 | next = (struct fw_cdev_iso_packet __user *) |
460 | &p->header[u.packet.header_length / 4]; | 475 | &p->header[header_length / 4]; |
461 | if (next > end) | 476 | if (next > end) |
462 | return -EINVAL; | 477 | return -EINVAL; |
463 | if (__copy_from_user | 478 | if (__copy_from_user |
464 | (u.packet.header, p->header, u.packet.header_length)) | 479 | (u.packet.header, p->header, header_length)) |
465 | return -EFAULT; | 480 | return -EFAULT; |
466 | if (u.packet.skip && | 481 | if (u.packet.skip && |
467 | u.packet.header_length + u.packet.payload_length > 0) | 482 | u.packet.header_length + u.packet.payload_length > 0) |