diff --git a/src/dispatch.c b/src/dispatch.c index 55d8327..10d1939 100644 --- a/src/dispatch.c +++ b/src/dispatch.c @@ -155,6 +155,20 @@ int raw1394_get_nodecount(raw1394handle_t handle) return ieee1394_get_nodecount(handle->mode.ieee1394); } +int raw1394_get_speed(raw1394handle_t handle, nodeid_t node) +{ + if (!handle) { + errno = EINVAL; + return -1; + } + if (handle->is_fw) + return fw_get_speed(handle->mode.fw, node); + else { + errno = ENOSYS; + return -1; + } +} + int raw1394_get_port_info(raw1394handle_t handle, struct raw1394_portinfo *pinf, int maxports) { diff --git a/src/fw.c b/src/fw.c index 877a6ad..7d64250 100644 --- a/src/fw.c +++ b/src/fw.c @@ -602,6 +602,34 @@ int fw_get_nodecount(fw_handle_t handle) return (handle->reset.root_node_id & 0x3f) + 1; } +int fw_get_speed(fw_handle_t handle, nodeid_t node) +{ + int i; + + if ((node & ~0x3f) != 0xffc0) { + errno = ENOSYS; + return -1; + } + + if (node > handle->reset.root_node_id) { + errno = fw_errcode_to_errno(-RCODE_NO_ACK); + return -1; + } + + i = handle->nodes[node & 0x3f]; + if (i == -1) { + errno = fw_errcode_to_errno(-RCODE_NO_ACK); + return -1; + } + + if (handle->generation != handle->devices[i].generation) { + errno = fw_errcode_to_errno(-RCODE_GENERATION); + return -1; + } + + return ioctl(handle->devices[i].fd, FW_CDEV_IOC_GET_SPEED); +} + int fw_get_port_info(fw_handle_t handle, struct raw1394_portinfo *pinf, int maxports) diff --git a/src/fw.h b/src/fw.h index 4fd660f..0a079c7 100644 --- a/src/fw.h +++ b/src/fw.h @@ -144,6 +144,7 @@ int fw_get_fd(fw_handle_t handle); nodeid_t fw_get_local_id(fw_handle_t handle); nodeid_t fw_get_irm_id(fw_handle_t handle); int fw_get_nodecount(fw_handle_t handle); +int fw_get_speed(fw_handle_t handle, nodeid_t node); int fw_get_port_info(fw_handle_t handle, struct raw1394_portinfo *pinf, int maxports); int fw_set_port(fw_handle_t handle, int port); diff --git a/src/raw1394.h b/src/raw1394.h index 486ba65..8787313 100644 --- a/src/raw1394.h +++ b/src/raw1394.h @@ -543,6 +543,22 @@ nodeid_t raw1394_get_irm_id(raw1394handle_t handle); **/ int raw1394_get_nodecount(raw1394handle_t handle); +/** + * raw1394_get_speed - get maximum speed between a node and local node + * @handle: libraw1394 handle + * @node: node ID + * + * Returns: The speed code of the maximum possible transmission speed between + * the node and the local node, taking both link speeds and all intermediate + * phy speeds into account. On error, returns -1 and sets errno. + * + * Bugs: Like much of the rest of the libraw1394 API, this call is prone to + * races with bus resets. + * + * History: New function in libraw1394 v2.1.0. + **/ +int raw1394_get_speed(raw1394handle_t handle, nodeid_t node); + struct raw1394_portinfo { int nodes; char name[32]; diff --git a/tools/testlibraw.c b/tools/testlibraw.c index b322a5d..fbeb273 100644 --- a/tools/testlibraw.c +++ b/tools/testlibraw.c @@ -229,7 +229,7 @@ int test_card(int card) struct raw1394_portinfo pinf; tag_handler_t std_handler; struct pollfd pfd; - int i, n, numcards, retval; + int i, l, n, numcards, retval, s; handle = raw1394_new_handle(); @@ -267,10 +267,22 @@ int test_card(int card) } n = raw1394_get_nodecount(handle); - printf("%d nodes on bus, local ID is %d, IRM is %d\n", - n, - raw1394_get_local_id(handle) & 0x3f, - raw1394_get_irm_id(handle) & 0x3f); + l = raw1394_get_local_id(handle) & 0x3f; + i = raw1394_get_irm_id(handle) & 0x3f; + printf("%d nodes on bus, local ID is %d, IRM is %d\n", n, l, i); + + if (n > 0) + printf("\n - getting speeds between between nodes and local node\n"); + for (i = 0; i < n; i++) { + printf(" node %d: ", i); + fflush(stdout); + s = raw1394_get_speed(handle, 0xffc0 | i); + if (s >= 0) + printf("S%d00%s\n", 1 << s, + i == l ? " (local node)" : ""); + else + perror("unknown"); + } if (n > 0) { printf("\n - doing transactions with custom tag handler\n");