diff mbox

[3/8] Documentation/spi/spidev_test.c: accept input from a file

Message ID d90d749776cf562bc9922aff5e97cb911a77b22b.1447773299.git.stillcompiling@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Joshua Clayton Nov. 17, 2015, 3:24 p.m. UTC
Add input file support to facilitate testing larger data.

Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
---
 Documentation/spi/spidev_test.c | 42 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 41 insertions(+), 1 deletion(-)

Comments

Anton Bondarenko Nov. 17, 2015, 6:26 p.m. UTC | #1
On 17.11.2015 16:24, Joshua Clayton wrote:
> Add input file support to facilitate testing larger data.
>
> Signed-off-by: Joshua Clayton <stillcompiling@gmail.com>
> ---
>   Documentation/spi/spidev_test.c | 42 ++++++++++++++++++++++++++++++++++++++++-
>   1 file changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
> index 1ed9110..ef812ad 100644
> --- a/Documentation/spi/spidev_test.c
> +++ b/Documentation/spi/spidev_test.c
> @@ -19,6 +19,7 @@
>   #include <getopt.h>
>   #include <fcntl.h>
>   #include <sys/ioctl.h>
> +#include <sys/stat.h>
>   #include <linux/types.h>
>   #include <linux/spi/spidev.h>
>
> @@ -33,6 +34,7 @@ static void pabort(const char *s)
>   static const char *device = "/dev/spidev1.1";
>   static uint32_t mode;
>   static uint8_t bits = 8;
> +static char *input_file;
>   static uint32_t speed = 500000;
>   static uint16_t delay;
>   static int verbose;
> @@ -144,6 +146,7 @@ static void print_usage(const char *prog)
>   	     "  -s --speed    max speed (Hz)\n"
>   	     "  -d --delay    delay (usec)\n"
>   	     "  -b --bpw      bits per word \n"
> +	     "  -i --input    input data from a file (e.g. \"test.bin\")\n"
>   	     "  -l --loop     loopback\n"
>   	     "  -H --cpha     clock phase\n"
>   	     "  -O --cpol     clock polarity\n"
> @@ -167,6 +170,7 @@ static void parse_opts(int argc, char *argv[])
>   			{ "speed",   1, 0, 's' },
>   			{ "delay",   1, 0, 'd' },
>   			{ "bpw",     1, 0, 'b' },
> +			{ "input",   1, 0, 'i' },
>   			{ "loop",    0, 0, 'l' },
>   			{ "cpha",    0, 0, 'H' },
>   			{ "cpol",    0, 0, 'O' },
> @@ -182,7 +186,8 @@ static void parse_opts(int argc, char *argv[])
>   		};
>   		int c;
>
> -		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, NULL);
> +		c = getopt_long(argc, argv, "D:s:d:b:i:lHOLC3NR24p:v",
> +				lopts, NULL);
>
>   		if (c == -1)
>   			break;
> @@ -200,6 +205,9 @@ static void parse_opts(int argc, char *argv[])
>   		case 'b':
>   			bits = atoi(optarg);
>   			break;
> +		case 'i':
> +			input_file = optarg;
> +			break;
>   		case 'l':
>   			mode |= SPI_LOOP;
>   			break;
> @@ -259,6 +267,33 @@ static void transfer_escaped_string(int fd, char *str)
>   	free(tx);
>   }
>
> +static void transfer_file(int fd, char *filename)
> +{
> +	ssize_t bytes;
> +	struct stat sb;
> +	int tx_fd;
> +	uint8_t *tx;
> +
> +	if (stat(filename, &sb) == -1)
> +		pabort("can't stat input file");
> +
> +	if (sb.st_size > 4096)
> +		pabort("input file exceeds spidev's 4k limit");
This is not a true. IIRC PAGE_SIZE is the default buffer size for 
spidev, but can be changed using bufsiz module parameter.
Just 'insmod spidev bufsiz=X', where X is number of bytes.
> +
> +	tx_fd = open(filename, O_RDONLY);
> +	if (fd < 0)
> +		pabort("can't open input file");
> +
> +	tx = malloc(sb.st_size);
It would be good to check new allocations for fail.
> +	bytes = read(tx_fd, tx, sb.st_size);
> +	if (bytes != sb.st_size)
> +		pabort("failed to read input file");
> +
> +	transfer(fd, tx, sb.st_size);
> +	free(tx);
> +	close(tx_fd);
> +}
> +
>   int main(int argc, char *argv[])
>   {
>   	int ret = 0;
> @@ -307,8 +342,13 @@ int main(int argc, char *argv[])
>   	printf("bits per word: %d\n", bits);
>   	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
>
> +	if (input_tx && input_file)
> +		pabort("only one of -p and --input may be selected");
> +
>   	if (input_tx)
>   		transfer_escaped_string(fd, input_tx);
> +	else if (input_file)
> +		transfer_file(fd, input_file);
>   	else
>   		transfer(fd, default_tx, sizeof(default_tx));
>
>
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Mark Brown Nov. 17, 2015, 6:46 p.m. UTC | #2
On Tue, Nov 17, 2015 at 07:26:54PM +0100, Anton Bondarenko wrote:
> On 17.11.2015 16:24, Joshua Clayton wrote:

> >+	if (sb.st_size > 4096)
> >+		pabort("input file exceeds spidev's 4k limit");

> This is not a true. IIRC PAGE_SIZE is the default buffer size for spidev,
> but can be changed using bufsiz module parameter.
> Just 'insmod spidev bufsiz=X', where X is number of bytes.

Right, there's also various options for changing PAGE_SIZE on some
architectures.  I was going to go and check what we actually do here but
in general it does seem better to just let the kernel worry about
validating things like this - it needs to do that anyway and it means
that if someone improves the kernel code to accept larger buffers then
the tool will automatically be able to use them instead of requiring
people to remember to separately update the tool.
Joshua Clayton Nov. 17, 2015, 7:28 p.m. UTC | #3
On Tuesday, November 17, 2015 07:26:54 PM Anton Bondarenko wrote:
> On 17.11.2015 16:24, Joshua Clayton wrote:
> > +	if (sb.st_size > 4096)
> > +		pabort("input file exceeds spidev's 4k limit");
> This is not a true. IIRC PAGE_SIZE is the default buffer size for 
> spidev, but can be changed using bufsiz module parameter.
> Just 'insmod spidev bufsiz=X', where X is number of bytes.

You are right. I will drop this. As Mark suggests.
The ioctl gives a nice error code if the buffer is too big.

...
> > +	tx = malloc(sb.st_size);
> It would be good to check new allocations for fail.

I will add a check for this.
diff mbox

Patch

diff --git a/Documentation/spi/spidev_test.c b/Documentation/spi/spidev_test.c
index 1ed9110..ef812ad 100644
--- a/Documentation/spi/spidev_test.c
+++ b/Documentation/spi/spidev_test.c
@@ -19,6 +19,7 @@ 
 #include <getopt.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <sys/stat.h>
 #include <linux/types.h>
 #include <linux/spi/spidev.h>
 
@@ -33,6 +34,7 @@  static void pabort(const char *s)
 static const char *device = "/dev/spidev1.1";
 static uint32_t mode;
 static uint8_t bits = 8;
+static char *input_file;
 static uint32_t speed = 500000;
 static uint16_t delay;
 static int verbose;
@@ -144,6 +146,7 @@  static void print_usage(const char *prog)
 	     "  -s --speed    max speed (Hz)\n"
 	     "  -d --delay    delay (usec)\n"
 	     "  -b --bpw      bits per word \n"
+	     "  -i --input    input data from a file (e.g. \"test.bin\")\n"
 	     "  -l --loop     loopback\n"
 	     "  -H --cpha     clock phase\n"
 	     "  -O --cpol     clock polarity\n"
@@ -167,6 +170,7 @@  static void parse_opts(int argc, char *argv[])
 			{ "speed",   1, 0, 's' },
 			{ "delay",   1, 0, 'd' },
 			{ "bpw",     1, 0, 'b' },
+			{ "input",   1, 0, 'i' },
 			{ "loop",    0, 0, 'l' },
 			{ "cpha",    0, 0, 'H' },
 			{ "cpol",    0, 0, 'O' },
@@ -182,7 +186,8 @@  static void parse_opts(int argc, char *argv[])
 		};
 		int c;
 
-		c = getopt_long(argc, argv, "D:s:d:b:lHOLC3NR24p:v", lopts, NULL);
+		c = getopt_long(argc, argv, "D:s:d:b:i:lHOLC3NR24p:v",
+				lopts, NULL);
 
 		if (c == -1)
 			break;
@@ -200,6 +205,9 @@  static void parse_opts(int argc, char *argv[])
 		case 'b':
 			bits = atoi(optarg);
 			break;
+		case 'i':
+			input_file = optarg;
+			break;
 		case 'l':
 			mode |= SPI_LOOP;
 			break;
@@ -259,6 +267,33 @@  static void transfer_escaped_string(int fd, char *str)
 	free(tx);
 }
 
+static void transfer_file(int fd, char *filename)
+{
+	ssize_t bytes;
+	struct stat sb;
+	int tx_fd;
+	uint8_t *tx;
+
+	if (stat(filename, &sb) == -1)
+		pabort("can't stat input file");
+
+	if (sb.st_size > 4096)
+		pabort("input file exceeds spidev's 4k limit");
+
+	tx_fd = open(filename, O_RDONLY);
+	if (fd < 0)
+		pabort("can't open input file");
+
+	tx = malloc(sb.st_size);
+	bytes = read(tx_fd, tx, sb.st_size);
+	if (bytes != sb.st_size)
+		pabort("failed to read input file");
+
+	transfer(fd, tx, sb.st_size);
+	free(tx);
+	close(tx_fd);
+}
+
 int main(int argc, char *argv[])
 {
 	int ret = 0;
@@ -307,8 +342,13 @@  int main(int argc, char *argv[])
 	printf("bits per word: %d\n", bits);
 	printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
 
+	if (input_tx && input_file)
+		pabort("only one of -p and --input may be selected");
+
 	if (input_tx)
 		transfer_escaped_string(fd, input_tx);
+	else if (input_file)
+		transfer_file(fd, input_file);
 	else
 		transfer(fd, default_tx, sizeof(default_tx));