aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClemens Ladisch <clemens@ladisch.de>2010-08-15 13:07:27 +0200
committerClemens Ladisch <clemens@ladisch.de>2012-05-18 13:44:55 +0200
commitbf4dfe57421e982c6981d79390f4a0ef7a93804c (patch)
tree6e03e70d2fef040fff3f049eaa0aeb0d20f3eadf
parent9712599ec6173324beec2912fad970f2ee929f4d (diff)
downloadlinux-firewire-utils-bf4dfe57421e982c6981d79390f4a0ef7a93804c.tar.gz
firewire-request: check source of FCP response
Accept FCP responses only from the device that we sent the FCP command to. This prevents displaying a wrong answer when there is parallel FCP communication with another device (but doesn't prevent them when another client is communicating with the same device).
-rw-r--r--src/firewire-request.c30
1 files changed, 24 insertions, 6 deletions
diff --git a/src/firewire-request.c b/src/firewire-request.c
index f0adec7..02cc2b3 100644
--- a/src/firewire-request.c
+++ b/src/firewire-request.c
@@ -24,6 +24,9 @@
#include <linux/firewire-constants.h>
#include <asm/byteorder.h>
+#define FCP_COMMAND_ADDR 0xfffff0000b00uLL
+#define FCP_RESPONSE_ADDR 0xfffff0000d00uLL
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof *(a))
#ifdef FW_CDEV_EVENT_REQUEST2
@@ -49,6 +52,8 @@ static unsigned int read_length;
static struct data data;
static struct data data2;
static int fd;
+static u32 card_index;
+static u32 node_id;
static u32 generation;
static void open_device(void)
@@ -75,6 +80,8 @@ static void open_device(void)
perror("GET_INFO ioctl failed");
exit(EXIT_FAILURE);
}
+ card_index = get_info.card;
+ node_id = bus_reset.node_id;
generation = bus_reset.generation;
}
@@ -325,7 +332,7 @@ static void do_fcp(void)
int ready, r;
struct fw_cdev_event_common *event;
- allocate.offset = 0xfffff0000d00uLL; /* FCP response */
+ allocate.offset = FCP_RESPONSE_ADDR;
allocate.closure = 0;
allocate.length = 0x200;
#ifdef USE_CDEV_ABI_4
@@ -338,7 +345,7 @@ static void do_fcp(void)
send_request.tcode = data.length == 4 ? TCODE_WRITE_QUADLET_REQUEST : TCODE_WRITE_BLOCK_REQUEST;
send_request.length = data.length;
- send_request.offset = 0xfffff0000b00uLL; /* FCP command */
+ send_request.offset = FCP_COMMAND_ADDR;
send_request.closure = 0;
send_request.data = (u64)data.data;
send_request.generation = generation;
@@ -382,14 +389,25 @@ static void do_fcp(void)
} else if (event->type == FW_CDEV_EVENT_REQUEST2) {
struct fw_cdev_event_request2 *request = (void *)buf;
send_response(request->handle, RCODE_COMPLETE);
- print_data("response: ", request->data, request->length, false);
- response_received = true;
+ if (request->card == card_index &&
+ (request->source_node_id & 0x3f) == (node_id & 0x3f) &&
+ (request->tcode == TCODE_WRITE_QUADLET_REQUEST ||
+ request->tcode == TCODE_WRITE_BLOCK_REQUEST) &&
+ request->offset == FCP_RESPONSE_ADDR &&
+ request->generation == generation) {
+ print_data("response: ", request->data, request->length, false);
+ response_received = true;
+ }
#endif
} else if (event->type == FW_CDEV_EVENT_REQUEST) {
struct fw_cdev_event_request *request = (void *)buf;
send_response(request->handle, RCODE_COMPLETE);
- print_data("response: ", request->data, request->length, false);
- response_received = true;
+ if ((request->tcode == TCODE_WRITE_QUADLET_REQUEST ||
+ request->tcode == TCODE_WRITE_BLOCK_REQUEST) &&
+ request->offset == FCP_RESPONSE_ADDR) {
+ print_data("response: ", request->data, request->length, false);
+ response_received = true;
+ }
}
}
}