aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Richter <stefanr@s5r6.in-berlin.de>2009-01-11 22:45:02 +0100
committerStefan Richter <stefanr@s5r6.in-berlin.de>2009-05-30 10:17:43 +0200
commitc58e16442b16f85d76808209c4aa7c37adc62de4 (patch)
tree3f21c9b5a6ea601c7dabf97f53c395aeac3b2d5e
parentda5156af5a5b779b6713ab7dff569a10927ed188 (diff)
downloadlibraw1394-c58e16442b16f85d76808209c4aa7c37adc62de4.tar.gz
Use new iso resource allocation ioctls
This allows raw1394_bandwidth_modify() and raw1394_channel_modify() to work on juju without write access to the IRM's character device file. If either the build-time requirement of firewire-cdev header ABI >= v.2 or the runtime requirement of firewire-core ABI >= v.2 is not satisfied, the code falls back to transactions to the IRM as before. Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
-rw-r--r--src/dispatch.c10
-rw-r--r--src/fw.c95
-rw-r--r--src/fw.h7
3 files changed, 110 insertions, 2 deletions
diff --git a/src/dispatch.c b/src/dispatch.c
index 49ceca2..d202424 100644
--- a/src/dispatch.c
+++ b/src/dispatch.c
@@ -541,7 +541,10 @@ int raw1394_bandwidth_modify (raw1394handle_t handle, unsigned int bandwidth,
errno = EINVAL;
return -1;
}
- return ieee1394_bandwidth_modify(handle, bandwidth, mode);
+ if (handle->is_fw)
+ return fw_bandwidth_modify(handle, bandwidth, mode);
+ else
+ return ieee1394_bandwidth_modify(handle, bandwidth, mode);
}
int raw1394_channel_modify (raw1394handle_t handle, unsigned int channel,
@@ -551,7 +554,10 @@ int raw1394_channel_modify (raw1394handle_t handle, unsigned int channel,
errno = EINVAL;
return -1;
}
- return ieee1394_channel_modify(handle, channel, mode);
+ if (handle->is_fw)
+ return fw_channel_modify(handle, channel, mode);
+ else
+ return ieee1394_channel_modify(handle, channel, mode);
}
int raw1394_iso_xmit_init(raw1394handle_t handle,
diff --git a/src/fw.c b/src/fw.c
index 9b33422..ae09fed 100644
--- a/src/fw.c
+++ b/src/fw.c
@@ -294,6 +294,13 @@ handle_device_event(raw1394handle_t handle,
ac = u64_to_ptr(u->request.closure);
return ac->callback(handle, ac, &u->request, i);
+#ifdef FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED /* added in kernel 2.6.30 */
+ case FW_CDEV_EVENT_ISO_RESOURCE_ALLOCATED:
+ case FW_CDEV_EVENT_ISO_RESOURCE_DEALLOCATED:
+ memcpy(u64_to_ptr(u->iso_resource.closure), u,
+ sizeof u->iso_resource);
+ return 0;
+#endif
default:
case FW_CDEV_EVENT_ISO_INTERRUPT:
/* Never happens. */
@@ -631,6 +638,7 @@ int fw_set_port(fw_handle_t handle, int port)
handle->local_device = &handle->devices[i];
handle->generation = reset.generation;
+ handle->abi_version = get_info.version;
i++;
}
@@ -1324,3 +1332,90 @@ fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer,
return 0;
}
+
+#ifdef FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE /* added in kernel 2.6.30 */
+
+static int
+iso_resource_modify(raw1394handle_t handle, unsigned int bandwidth,
+ int channel, enum raw1394_modify_mode mode)
+{
+ fw_handle_t fwhandle = handle->mode.fw;
+ struct fw_cdev_allocate_iso_resource resource;
+ struct fw_cdev_event_iso_resource event;
+ int ioctl_nr;
+ int err;
+
+ if (channel > 63) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ event.closure = 0;
+ event.channel = -1;
+ event.bandwidth = 0;
+
+ resource.closure = ptr_to_u64(&event);
+ resource.channels = channel >= 0 ? 1ULL << channel : 0;
+ resource.bandwidth = bandwidth;
+
+ ioctl_nr = mode == RAW1394_MODIFY_ALLOC ?
+ FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE :
+ FW_CDEV_IOC_DEALLOCATE_ISO_RESOURCE_ONCE;
+
+ err = ioctl(fwhandle->ioctl_fd, ioctl_nr, &resource);
+
+ while (err >= 0 && event.closure != resource.closure)
+ err = fw_loop_iterate(handle);
+
+ if (err < 0)
+ return err;
+
+ if ((channel >= 0 && event.channel < 0) ||
+ (bandwidth > 0 && event.bandwidth == 0)) {
+ errno = EIO;
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int abi_v2_available(raw1394handle_t handle)
+{
+ return handle->mode.fw->abi_version >= 2;
+}
+
+#else
+
+static inline int
+iso_resource_modify(raw1394handle_t handle, unsigned int bandwidth,
+ int channel, enum raw1394_modify_mode mode)
+{
+ return -1;
+}
+
+static inline int abi_v2_available(raw1394handle_t handle)
+{
+ return 0;
+}
+
+#endif /* defined(FW_CDEV_IOC_ALLOCATE_ISO_RESOURCE_ONCE) */
+
+int
+fw_bandwidth_modify(raw1394handle_t handle, unsigned int bandwidth,
+ enum raw1394_modify_mode mode)
+{
+ if (abi_v2_available(handle))
+ return iso_resource_modify(handle, bandwidth, -1, mode);
+ else
+ return ieee1394_bandwidth_modify(handle, bandwidth, mode);
+}
+
+int
+fw_channel_modify(raw1394handle_t handle, unsigned int channel,
+ enum raw1394_modify_mode mode)
+{
+ if (abi_v2_available(handle))
+ return iso_resource_modify(handle, 0, channel, mode);
+ else
+ return ieee1394_channel_modify(handle, channel, mode);
+}
diff --git a/src/fw.h b/src/fw.h
index 2d8ee38..ffd2c05 100644
--- a/src/fw.h
+++ b/src/fw.h
@@ -81,6 +81,7 @@ struct fw_handle {
int port_count;
int err;
int generation;
+ int abi_version;
void *userdata;
int notify_bus_reset;
@@ -202,6 +203,12 @@ int fw_update_config_rom(fw_handle_t handle, const quadlet_t *new_rom,
int fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer,
size_t buffersize, size_t *rom_size,
unsigned char *rom_version);
+int fw_bandwidth_modify(raw1394handle_t handle,
+ unsigned int bandwidth,
+ enum raw1394_modify_mode mode);
+int fw_channel_modify(raw1394handle_t handle,
+ unsigned int channel,
+ enum raw1394_modify_mode mode);
int fw_iso_xmit_start(raw1394handle_t handle, int start_on_cycle,
int prebuffer_packets);