Tweak raw1394_add_config_rom_descriptor() API, add documentation and test case

To conform with 'size' arguments of other libraw1394 calls, change the one in
raw1394_add_config_rom_descriptor() from quadlets to bytes.  This breaks runtime
compatibility with potential clients that were written against B.J.'s original
patch, hence reorder arguments just to break compatibility also at compile time.

Change errno to ENOSYS (function not implemented) when called while running on
top of raw1394.

Allow &token to be NULL for convenience of clients which don't require
raw1394_remove_config_rom_descriptor().

Add exhaustive documentation.  Much of it is copied from the documentation of
the underlying ioctl.

Add example code which doubles as unit test in testlibraw.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
This commit is contained in:
Stefan Richter 2012-06-18 00:03:37 +02:00
parent f3c9af36c2
commit 56056a9607
5 changed files with 128 additions and 41 deletions

View File

@ -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;
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -15,6 +15,7 @@
#include <sys/poll.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <arpa/inet.h>
#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