summaryrefslogtreecommitdiff
path: root/drivers/firewire/fw-cdev.c
diff options
context:
space:
mode:
authorJay Fenlason <fenlason@redhat.com>2009-03-05 19:08:40 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-03-24 20:56:49 +0100
commitf8c2287c65f8f72000102fc058232669e4540bc4 (patch)
treea82393fbdd3a2b20f8e499537b10eb9e61dae941 /drivers/firewire/fw-cdev.c
parentba27e1f7bf220799cd3d7503f82bda71b8ebe8c5 (diff)
firewire: implement asynchronous stream transmission
Allow userspace and other firewire drivers (fw-ipv4 I'm looking at you!) to send Asynchronous Transmit Streams as described in 7.8.3 of release 1.1 of the 1394 Open Host Controller Interface Specification. Signed-off-by: Jay Fenlason <fenlason@redhat.com> Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de> (tweaks)
Diffstat (limited to 'drivers/firewire/fw-cdev.c')
-rw-r--r--drivers/firewire/fw-cdev.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/drivers/firewire/fw-cdev.c b/drivers/firewire/fw-cdev.c
index 214e534efee5..539dae5eb5b2 100644
--- a/drivers/firewire/fw-cdev.c
+++ b/drivers/firewire/fw-cdev.c
@@ -1242,6 +1242,38 @@ static int ioctl_send_broadcast_request(struct client *client, void *buffer)
return init_request(client, request, LOCAL_BUS | 0x3f, SCODE_100);
}
+struct stream_packet {
+ struct fw_packet packet;
+ u8 data[0];
+};
+
+static void send_stream_packet_done(struct fw_packet *packet,
+ struct fw_card *card, int status)
+{
+ kfree(container_of(packet, struct stream_packet, packet));
+}
+
+static int ioctl_send_stream_packet(struct client *client, void *buffer)
+{
+ struct fw_cdev_send_stream_packet *request = buffer;
+ struct stream_packet *p;
+
+ p = kmalloc(sizeof(*p) + request->size, GFP_KERNEL);
+ if (p == NULL)
+ return -ENOMEM;
+
+ if (request->data &&
+ copy_from_user(p->data, u64_to_uptr(request->data), request->size)) {
+ kfree(p);
+ return -EFAULT;
+ }
+ fw_send_stream_packet(client->device->card, &p->packet,
+ request->generation, request->speed,
+ request->channel, request->sy, request->tag,
+ p->data, request->size, send_stream_packet_done);
+ return 0;
+}
+
static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
ioctl_get_info,
ioctl_send_request,
@@ -1262,6 +1294,7 @@ static int (* const ioctl_handlers[])(struct client *client, void *buffer) = {
ioctl_deallocate_iso_resource_once,
ioctl_get_speed,
ioctl_send_broadcast_request,
+ ioctl_send_stream_packet,
};
static int dispatch_ioctl(struct client *client,