Re: This is where I'm going with fwcontrol

Sean Bruno <[email protected]>
Newsgroups gmane.os.freebsd.devel.firewire
Message-ID <[email protected]>
Sean Bruno wrote:
> Take a look at what I'm doing with fwcontrol if you have time.
>
> I'm modifying it such that it can find nodes on different "buses" or 
> cards and allowing it to parse all arguments before execution begins.  
> It's in the primitive stages right now and I'd really like to know 
> what you think.
>
> Here is a current diff against RELENG_7 which seems to be the same as 
> -CURRENT.
>
> Sean
> ------------------------------------------------------------------------
>
> _______________________________________________
> [email protected] mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-firewire
> To unsubscribe, send any mail to "[email protected]"
Here is today's version of fwcontrol.  

SUMMARY:
-- cleanup a couple of memory leaks missing free's
-- add "-p" to the usage display
-- rework main() while loop to not act on arguments.  Store those 
arguments so that multiple arguments can be passed on the command line. 
              example:  sudo fwcontrol -u 1 -r -o
--  Allow code to use "-u" to denote a different /dev/fwX device other 
thatn /dev/fw0.  This allows commands like a bus reset to act on a 
second firewire bus/card.
--  Maintain backwards compatibility when "-u" is not used to mean that 
the command is to use /dev/fw0
-- Minor break to compatiblity.  If fwcontrol is run with no arguments 
and there is more that one /dev/fwX device, it will iterate across all 
devices.  Old behavior was to simply display the first device.

I'd like some review of the code from anyone who has the time.  I think 
that this is worth while to merge into -CURRENT and possibly back into 
7.0 and 6.3 as I spent some considerable time on emulating the old behavior.

I cannot test the -S/R/M arguments as I do not have a firewire video 
camera and would love to know if I've broken anything!  :)



-- 
Sean Bruno
MiraLink Corporation
6015 NE 80th Ave, Ste 100
Portland, OR 97218
Phone 503-621-5143
Fax 503-621-5199

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-firewire
To unsubscribe, send any mail to "[email protected]"
fwcontrol.c.diff (text/x-patch, 11.5 KB)
Index: fwcontrol.c
===================================================================
--- fwcontrol.c	(revision 5540)
+++ fwcontrol.c	(working copy)
@@ -81,6 +81,7 @@
 		"\t-l: load and parse hex dump file of configuration ROM\n"
 		"\t-R: Receive DV or MPEG TS stream\n"
 		"\t-S: Send DV stream\n"
+		"\t-p: Display current PHY register settings\n"
 		"\t-m: set fwmem target\n");
 	exit(EX_USAGE);
 }
@@ -92,18 +93,14 @@
 	*(u_int32_t*)&(eui->octet[4]) = htonl(fweui->lo);
 }
 
-static struct fw_devlstreq *
-get_dev(int fd)
+static void
+get_dev(int fd, struct fw_devlstreq *data)
 {
-	struct fw_devlstreq *data;
-
-	data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
 	if (data == NULL)
 		err(1, "malloc");
 	if( ioctl(fd, FW_GDEVLST, data) < 0) {
        			err(1, "ioctl");
 	}
-	return data;
 }
 
 static int
@@ -130,17 +127,23 @@
 	if (eui64_hostton(nodestr, &eui) != 0 && eui64_aton(nodestr, &eui) != 0)
 		return (-1);
 
-	data = get_dev(fd);
+	data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
+	get_dev(fd,data);
 
 	for (i = 0; i < data->info_len; i++) {
 		fweui2eui64(&data->dev[i].eui, &tmpeui);
 		if (memcmp(&eui, &tmpeui, sizeof(struct eui64)) == 0) {
 			node = data->dev[i].dst;
+			if (data != NULL)
+				free(data);
 			goto gotnode;
 		}
 	}
-	if (i >= data->info_len)
+	if (i >= data->info_len) {
+		if (data != NULL)
+			free(data);
 		return (-1);
+	}
 
 gotnode:
 	if (node < 0 || node > 63)
@@ -158,7 +161,8 @@
 	char addr[EUI64_SIZ], hostname[40];
 	int i;
 
-	data = get_dev(fd);
+	data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
+	get_dev(fd, data);
 	printf("%d devices (info_len=%d)\n", data->n, data->info_len);
 	printf("node           EUI64          status    hostname\n");
 	for (i = 0; i < data->info_len; i++) {
@@ -242,7 +246,7 @@
 }
 
 static void
-send_link_on(int fd, int node)
+link_on(int fd, int node)
 {
         struct fw_asyreq *asyreq;
 
@@ -290,7 +294,8 @@
 	u_int32_t max, reg, old;
 	int i;
 
-	data = get_dev(fd);
+	data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
+	get_dev(fd, data);
 #define BUGET_REG 0xf0000218
 	for (i = 0; i < data->info_len; i++) {
 		devinfo = &data->dev[i];
@@ -344,7 +349,8 @@
 	int i, error;
 	struct fw_devlstreq *data;
 
-	data = get_dev(fd);
+	data = (struct fw_devlstreq *)malloc(sizeof(struct fw_devlstreq));
+	get_dev(fd, data);
 
 	for (i = 0; i < data->info_len; i++) {
 		if (data->dev[i].dst == node && data->dev[i].eui.lo != 0)
@@ -590,22 +596,16 @@
 	);
 }
 
-static void
-open_dev(int *fd, char *devbase)
+static int
+open_dev(int *fd, char *devname)
 {
-	char name[256];
-	int i;
-
 	if (*fd < 0) {
-		for (i = 0; i < 4; i++) {
-			snprintf(name, sizeof(name), "%s.%d", devbase, i);
-			if ((*fd = open(name, O_RDWR)) >= 0)
-				break;
-		}
+		*fd = open(devname, O_RDWR);
 		if (*fd < 0)
-			err(1, "open");
+			return(-1);
 
 	}
+	return(0);
 }
 
 static void
@@ -666,99 +666,147 @@
 int
 main(int argc, char **argv)
 {
+#define MAX_BOARDS 10
 	u_int32_t crom_buf[1024/4];
-	char devbase[1024] = "/dev/fw0";
-	int fd, ch, len=1024;
+	u_int32_t crom_buf_hex[1024/4];
+	char devbase[64];
+	const char *device_string = "/dev/fw";
+	int fd = -1, ch, len=1024;
+	int current_board = 0;
+ /*
+  * If !command_set, then -u will display the nodes for the board.
+  * This emulates the previous behavior when -u is passed by itself
+  */
+	int command_set = 0;
+	int open_needed = 0;
 	long tmp;
 	struct fw_eui64 eui;
 	struct eui64 target;
 	fwmethod *recvfn = NULL;
+/*
+ * Holders for which functions
+ * to iterate through
+ */
+	int display_board_only = 0;
+	int priority_budget = 0;
+	int display_crom = 0;
+	char *crom_string = NULL;
+	char *crom_string_hex = NULL;
+	int display_crom_hex = 0;
+	int adjust_gap_count = 0;
+	int reset_gap_count = 0;
+	int load_crom_from_file = 0;
+	int set_fwmem_target = 0;
+	long dump_phy_reg = 0;
+	int dump_topology = 0;
+	long send_link_on = 0;
+	int send_bus_reset = 0;
+	long send_reset_start = 0;
+	char *recv_data = NULL;
+	char *send_data = NULL;
 
-	fd = -1;
-
 	if (argc < 2) {
-		open_dev(&fd, devbase);
-		list_dev(fd);
+		for (current_board = 0; current_board < MAX_BOARDS; current_board++) {
+			snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board);
+			if (open_dev(&fd, devbase) < 0) {
+				return(0);
+			}
+			list_dev(fd);
+			close(fd);
+			fd = -1;
+		}
 	}
-
-	while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1)
+       /*
+	* Parse all command line options, then execute requested operations.
+	*/
+	while ((ch = getopt(argc, argv, "M:f:g:m:o:s:b:prtc:d:l:u:R:S:")) != -1) {
 		switch(ch) {
 		case 'b':
-			tmp = strtol(optarg, NULL, 0);
-			if (tmp < 0 || tmp > (long)0xffffffff)
+			priority_budget = strtol(optarg, NULL, 0);
+			if (priority_budget < 0 || priority_budget > (long)0xffffffff)
 				errx(EX_USAGE, "invalid number: %s", optarg);
-			open_dev(&fd, devbase);
-			set_pri_req(fd, tmp);
+			command_set = 1;
+			open_needed = 1;
+			display_board_only = 0;
 			break;
 		case 'c':
-			open_dev(&fd, devbase);
-			tmp = str2node(fd, optarg);
-			get_crom(fd, tmp, crom_buf, len);
-			show_crom(crom_buf);
+			crom_string = malloc(strlen(optarg)+1);
+			strcpy(crom_string, optarg);
+			display_crom = 1;
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'd':
-			open_dev(&fd, devbase);
-			tmp = str2node(fd, optarg);
-			get_crom(fd, tmp, crom_buf, len);
-			dump_crom(crom_buf);
+			crom_string_hex = malloc(strlen(optarg)+1);
+			strcpy(crom_string_hex, optarg);
+			display_crom_hex = 1;
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'f':
-			tmp = strtol(optarg, NULL, 0);
-			open_dev(&fd, devbase);
-			send_phy_config(fd, tmp, -1);
+			adjust_gap_count = strtol(optarg, NULL, 0);
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'g':
-			tmp = strtol(optarg, NULL, 0);
-			open_dev(&fd, devbase);
-			send_phy_config(fd, -1, tmp);
+			reset_gap_count = strtol(optarg, NULL, 0);
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'l':
+			load_crom_from_file = 1;
 			load_crom(optarg, crom_buf);
-			show_crom(crom_buf);
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'm':
-		       if (eui64_hostton(optarg, &target) != 0 &&
-			   eui64_aton(optarg, &target) != 0)
+			set_fwmem_target = 1;
+			open_needed = 0;
+			command_set = 1;
+			display_board_only = 0;
+			if (eui64_hostton(optarg, &target) != 0 &&
+			    eui64_aton(optarg, &target) != 0)
 				errx(EX_USAGE, "invalid target: %s", optarg);
-			eui.hi = ntohl(*(u_int32_t*)&(target.octet[0]));
-			eui.lo = ntohl(*(u_int32_t*)&(target.octet[4]));
-			sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi);
-			sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo);
 			break;
 		case 'o':
-			open_dev(&fd, devbase);
-			tmp = str2node(fd, optarg);
-			send_link_on(fd, tmp);
+			send_link_on = str2node(fd, optarg);
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'p':
-			open_dev(&fd, devbase);
-			dump_phy_registers(fd);
+			dump_phy_reg = 1;
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'r':
-			open_dev(&fd, devbase);
-			if(ioctl(fd, FW_IBUSRST, &tmp) < 0)
-                       		err(1, "ioctl");
+			send_bus_reset = 1;
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 's':
-			open_dev(&fd, devbase);
-			tmp = str2node(fd, optarg);
-			reset_start(fd, tmp);
+			send_reset_start  = str2node(fd, optarg);
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 't':
-			open_dev(&fd, devbase);
-			show_topology_map(fd);
+			dump_topology = 1;
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'u':
-			tmp = strtol(optarg, NULL, 0);
-			snprintf(devbase, sizeof(devbase), "/dev/fw%ld", tmp);
-			if (fd > 0) {
-				close(fd);
-				fd = -1;
-			}
-			if (argc == optind) {
-				open_dev(&fd, devbase);
-				list_dev(fd);
-			}
+			if(!command_set)
+				display_board_only = 1;
+			current_board = strtol(optarg, NULL, 0);
+			open_needed = 1;
 			break;
 #define TAG	(1<<6)
 #define CHANNEL	63
@@ -774,22 +822,151 @@
 				errx(EX_USAGE, "unrecognized method: %s",
 				    optarg);
 			}
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'R':
-			open_dev(&fd, devbase);
-			if (recvfn == NULL) /* guess... */
-				recvfn = detect_recv_fn(fd, TAG | CHANNEL);
-			close(fd);
-			fd = -1;
-			open_dev(&fd, devbase);
-			(*recvfn)(fd, optarg, TAG | CHANNEL, -1);
+			recv_data = malloc(strlen(optarg)+1);
+			strcpy(recv_data, optarg);
+			open_needed = 1;
+			command_set = 1;
+			display_board_only = 0;
 			break;
 		case 'S':
-			open_dev(&fd, devbase);
-			dvsend(fd, optarg, TAG | CHANNEL, -1);
+			send_data = malloc(strlen(optarg)+1);
+			strcpy(send_data, optarg);
+			open_needed = 1;
+			display_board_only = 0;
 			break;
 		default:
 			usage();
+			return 0;
 		}
+	} /* end while */
+
+       /*
+	* If -u <bus_number> is passed, execute 
+	* command for that card only.
+	*
+	* If -u <bus_number> is not passed, execute
+	* command for card 0 only. 
+	*
+	*/
+	if(open_needed){
+		snprintf(devbase, sizeof(devbase), "%s%d", device_string, current_board);
+		if (open_dev(&fd, devbase) < 0)
+			return(EIO);
+	}
+	/*
+	 * display the nodes on this board "-u"
+	 * only
+	 */
+	if (display_board_only)
+		list_dev(fd);
+
+	/*
+	 * dump_phy_reg "-p" 
+	 */
+	if (dump_phy_reg)
+		dump_phy_registers(fd);
+			
+	/*
+	 * send a BUS_RESET Event "-r"
+	 */
+	if (send_bus_reset) {
+		if(ioctl(fd, FW_IBUSRST, &tmp) < 0)
+               		err(1, "ioctl");
+	}
+	/*
+	 * Print out the CROM for this node "-c"
+	 */
+	if (display_crom) {
+		tmp = str2node(fd, crom_string);
+		get_crom(fd, tmp, crom_buf, len);
+		show_crom(crom_buf);
+		free(crom_string);
+	}
+	/*
+	 * Hex Dump the CROM for this node "-d"
+	 */
+	if (display_crom_hex) {
+		tmp = str2node(fd, crom_string_hex);
+		get_crom(fd, tmp, crom_buf_hex, len);
+		dump_crom(crom_buf_hex);
+		free(crom_string_hex);
+	}
+	/*
+	 * Set Priority Budget to value for this node "-b"
+	 */
+	if (priority_budget)
+		set_pri_req(fd, priority_budget);
+
+	/*
+	 * Adjust the gap count for this card/bus to value "-f"
+	 */
+	if (adjust_gap_count)
+		send_phy_config(fd, adjust_gap_count, -1);
+
+	/*
+	 * Reset the gap count for this card/bus  "-g"
+	 */
+	if (reset_gap_count)
+		send_phy_config(fd, -1, tmp);
+
+	/*
+	 * Load a CROM from a file "-l"
+	 */
+	if (load_crom_from_file)
+		show_crom(crom_buf);
+	/*
+	 * Set the fwmem target for a node to argument "-m"
+	 */
+	if (set_fwmem_target) {
+		eui.hi = ntohl(*(u_int32_t*)&(target.octet[0]));
+		eui.lo = ntohl(*(u_int32_t*)&(target.octet[4]));
+		sysctl_set_int("hw.firewire.fwmem.eui64_hi", eui.hi);
+		sysctl_set_int("hw.firewire.fwmem.eui64_lo", eui.lo);
+	}
+
+	/*
+	 * Send a link on to this board/bus "-o"
+	 */
+	if (send_link_on)
+		link_on(fd, send_link_on);
+
+	/*
+	 * Send a reset start to this board/bus "-s"
+	 */
+	if (send_reset_start)
+		reset_start(fd, send_reset_start);
+
+	/*
+	 * Dump the node topology for this board/bus "-t"
+	 */
+	if (dump_topology)
+		show_topology_map(fd);
+
+	/*
+	 * Recieve data file from node "-R"
+	 */
+	if (recv_data != NULL){
+		if (recvfn == NULL) /* guess... */
+			recvfn = detect_recv_fn(fd, TAG | CHANNEL);
+		(*recvfn)(fd, recv_data, TAG | CHANNEL, -1);
+		free(recv_data);
+	}
+
+	/*
+	 * Send data file to node "-S"
+	 */
+	if (send_data != NULL){
+		dvsend(fd, send_data, TAG | CHANNEL, -1);
+		free(send_data);
+	}
+
+	if (fd > 0) {
+		close(fd);
+		fd = -1;
+	}
 	return 0;
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.