diff --git a/src/dispatch.c b/src/dispatch.c index 1cc8e6a..601ee78 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -519,27 +519,24 @@ int raw1394_update_config_rom(raw1394handle_t handle, const quadlet_t new_rom, size, rom_version); } -int raw1394_add_config_rom_descriptor(raw1394handle_t handle, - const quadlet_t immediate_key, - const quadlet_t key, - const quadlet_t *new_rom_directory, - size_t size, - __u32 *out_token) +int raw1394_add_config_rom_descriptor(raw1394handle_t handle, u_int32_t *token, + quadlet_t immediate_key, quadlet_t key, + const quadlet_t *data, size_t size) { if (!handle) { errno = EINVAL; return -1; } if (handle->is_fw) - return fw_add_config_rom_descriptor(handle->mode.fw, - immediate_key, key, new_rom_directory, size, out_token); + return fw_add_config_rom_descriptor(handle->mode.fw, token, + immediate_key, key, data, size); else { - errno = EINVAL; + errno = ENOSYS; return -1; } } -int raw1394_remove_config_rom_descriptor(raw1394handle_t handle, __u32 token) +int raw1394_remove_config_rom_descriptor(raw1394handle_t handle, u_int32_t token) { if (!handle) { errno = EINVAL; @@ -548,7 +545,7 @@ int raw1394_remove_config_rom_descriptor(raw1394handle_t handle, __u32 token) if (handle->is_fw) return fw_remove_config_rom_descriptor(handle->mode.fw, token); else { - errno = EINVAL; + errno = ENOSYS; return -1; } } diff --git a/src/fw.c b/src/fw.c index da275c5..877a6ad 100644 --- a/src/fw.c +++ b/src/fw.c @@ -1543,35 +1543,34 @@ fw_update_config_rom(fw_handle_t handle, const quadlet_t *new_rom, } int -fw_add_config_rom_descriptor(fw_handle_t handle, - const quadlet_t immediate_key, - const quadlet_t key, - const quadlet_t *new_rom_directory, - size_t size, - __u32 *out_token) +fw_add_config_rom_descriptor(fw_handle_t handle, u_int32_t *token, + quadlet_t immediate_key, quadlet_t key, + const quadlet_t *data, size_t size) { struct fw_cdev_add_descriptor request; - int retval; + int err; request.immediate = immediate_key; request.key = key; - request.data = ptr_to_u64(new_rom_directory); - request.length = size; + request.data = ptr_to_u64(data); + request.length = size / 4; request.handle = 0; - retval = ioctl(handle->local_device->fd, FW_CDEV_IOC_ADD_DESCRIPTOR, - &request); - if (retval < 0) - return -1; + err = ioctl(handle->local_device->fd, FW_CDEV_IOC_ADD_DESCRIPTOR, + &request); + if (err) + return err; + + if (token) + *token = request.handle; - *out_token = request.handle; return 0; } int -fw_remove_config_rom_descriptor(fw_handle_t handle, __u32 token) +fw_remove_config_rom_descriptor(fw_handle_t handle, u_int32_t token) { - struct fw_cdev_remove_descriptor request = {token}; + struct fw_cdev_remove_descriptor request = {.handle = token}; return ioctl(handle->local_device->fd, FW_CDEV_IOC_REMOVE_DESCRIPTOR, &request); diff --git a/src/fw.h b/src/fw.h index e64b2f3..cb1df01 100644 --- a/src/fw.h +++ b/src/fw.h @@ -202,13 +202,10 @@ int fw_start_fcp_listen(fw_handle_t handle); int fw_stop_fcp_listen(fw_handle_t handle); int fw_update_config_rom(fw_handle_t handle, const quadlet_t *new_rom, size_t size, unsigned char rom_version); -int fw_add_config_rom_descriptor(fw_handle_t handle, - const quadlet_t immediate_key, - const quadlet_t key, - const quadlet_t *new_rom_directory, - size_t size, - __u32 *out_token); -int fw_remove_config_rom_descriptor(fw_handle_t handle, __u32 token); +int fw_add_config_rom_descriptor(fw_handle_t handle, u_int32_t *token, + quadlet_t immediate_key, quadlet_t key, + const quadlet_t *data, size_t size); +int fw_remove_config_rom_descriptor(fw_handle_t handle, u_int32_t token); int fw_get_config_rom(fw_handle_t handle, quadlet_t *buffer, size_t buffersize, size_t *rom_size, unsigned char *rom_version); diff --git a/src/raw1394.h b/src/raw1394.h index 7239de3..312c3b3 100644 --- a/src/raw1394.h +++ b/src/raw1394.h @@ -1160,18 +1160,69 @@ const char *raw1394_get_libversion(void); * Returns: -1 (failure) if the version is incorrect, * -2 (failure) if the new rom version is too big, or * 0 for success + * + * This function always fails on current kernels. **/ int raw1394_update_config_rom(raw1394handle_t handle, const quadlet_t *new_rom, size_t size, unsigned char rom_version); -int raw1394_add_config_rom_descriptor(raw1394handle_t handle, - const quadlet_t immediate_key, - const quadlet_t key, - const quadlet_t *new_rom_directory, - size_t size, - u_int32_t *out_token); +/** + * raw1394_add_config_rom_descriptor - add contents to local Configuration ROM + * @handle: libraw1394 handle + * @token: handle of the Configuration ROM contents, written by libraw1394 + * @immediate_key: if non-zero, immediate key to insert before pointer + * @key: upper 8 bits of root directory pointer + * @data: pointer to contents of descriptor block + * @size: size of descriptor block data, in bytes + * + * Add a directory, descriptor, or leaf block and optionally a preceding + * immediate key to the local node's Configuration ROM. If successful, the + * kernel adds the descriptor and generates a bus reset to signal the change of + * the Configuration ROM to other nodes. Note, on a system with multiple cards + * (multiple libraw1394 ports), the Configuration ROM of all local nodes is + * changed, not just the one which corresponds to the @handle. + * + * The changes to the Configuration ROM will be reverted when the client exits, + * or by raw1394_destroy_handle(), or by raw1394_remove_config_rom_descriptor(). + * In order to be able to call the latter, the client needs to provide @token as + * pointer to an u_int32_t variable; otherwise @token may be NULL. + * + * @key specifies the upper 8 bits of the descriptor root directory pointer and + * @data and @size specify the contents. The @key should be of the form + * 0xXX000000. The offset part of the root directory entry will be filled in by + * the kernel. + * + * If not 0, @immediate_key specifies an immediate key which will be inserted + * before the root directory pointer. + * + * A directory can be added together with further subdirectories or descriptors + * or other leaves; just provide all data concatenated in @data and set the + * respective offsets in your directory entries. + * + * The CRC in the first quadlet of any directory, subdirectory, leaf or + * descriptor may be left blank. The kernel will compute and fill in these + * CRCs. + * + * @immediate_key, @key, and @data array elements are host-endian quadlets. + * + * Returns: 0 on success or -1 on failure (sets errno) + * + * History: New function in libraw1394 v2.1.0. + **/ +int raw1394_add_config_rom_descriptor(raw1394handle_t handle, u_int32_t *token, + quadlet_t immediate_key, quadlet_t key, + const quadlet_t *data, size_t size); +/** + * raw1394_remove_config_rom_descriptor - remove contents from Configuration ROM + * @handle: libraw1394 handle + * @token: handle of the Configuration ROM contents + * + * Returns: 0 on success or -1 on failure (sets errno) + * + * History: New function in libraw1394 v2.1.0. + **/ int raw1394_remove_config_rom_descriptor(raw1394handle_t handle, u_int32_t token); diff --git a/tools/testlibraw.c b/tools/testlibraw.c index 6547c00..8fe8b26 100644 --- a/tools/testlibraw.c +++ b/tools/testlibraw.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include "../src/raw1394.h" @@ -117,10 +118,36 @@ read_topology_map(raw1394handle_t handle) printf(" 0x%08x\n", ntohl(map[3 + i])); } +static const quadlet_t unit_directory_data[] = { + 0x00060000, /* directory_length (CRC left blank) */ + 0x1258595a, /* a bogus unit_specifier_id: XYZ */ + 0x13616263, /* unit_sw_version: abc */ + 0x036c7277, /* a bogus vendor OUI: lrw */ + 0x81000003, /* textual descriptor offset */ + 0x17000001, /* model: 1 */ + 0x81000007, /* textual descriptor offset */ + + 0x00050000, /* descriptor_length (CRC left blank) */ + 0x00000000, /* descriptor_type: text */ + 0x00000000, /* minimal ASCII, English */ + 0x6c696272, /* "libr" */ + 0x61773133, /* "aw13" */ + 0x39340000, /* "94" */ + + 0x00050000, /* descriptor_length (CRC left blank) */ + 0x00000000, /* descriptor_type: text */ + 0x00000000, /* minimal ASCII, English */ + 0x74657374, /* "test" */ + 0x6c696272, /* "libr" */ + 0x61770000, /* "aw" */ +}; +#define IEEE1212_KEY_UNIT_DIRECTORY 0xd1000000 + static void test_config_rom(raw1394handle_t handle) { quadlet_t rom[0x100] = { 0, }; + u_int32_t token; size_t rom_size; unsigned char rom_version; int i, retval; @@ -135,7 +162,23 @@ test_config_rom(raw1394handle_t handle) printf(" 0x%08x\n", rom[i]); retval = raw1394_update_config_rom(handle, rom, rom_size, rom_version); - printf(" update_config_rom returned %d\n", retval); + perror(" raw1394_update_config_rom failed with error"); + + retval = raw1394_add_config_rom_descriptor(handle, &token, + 0, IEEE1212_KEY_UNIT_DIRECTORY, + unit_directory_data, sizeof(unit_directory_data)); + if (retval) { + printf(" raw1394_add_config_rom_descriptor failed with error"); + return; + } + + printf(" added unit '0x58595a:0x616263', reverting in 5 seconds\n"); + sleep(5); + retval = raw1394_remove_config_rom_descriptor(handle, token); + if (retval) + printf(" raw1394_remove_config_rom_descriptor failed with error"); + else + printf(" unit '0x58595a:0x616263' removed\n"); } static void