View | Details | Raw Unified | Return to bug 198817 | Differences between
and this patch

Collapse All | Expand All

(-)b/usr.sbin/i2c/i2c.8 (-2 / +20 lines)
Lines 1-5 Link Here
1
.\"
1
.\"
2
.\" Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka
2
.\" Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka
3
.\" Copyright (C) 2015 Emmanuel Vadot <manu@bidouilliste.com>
3
.\" All rights reserved.
4
.\" All rights reserved.
4
.\"
5
.\"
5
.\" Redistribution and use in source and binary forms, with or without
6
.\" Redistribution and use in source and binary forms, with or without
Lines 25-31 Link Here
25
.\"
26
.\"
26
.\" $FreeBSD$
27
.\" $FreeBSD$
27
.\"
28
.\"
28
.Dd January 23, 2009
29
.Dd July 5, 2015
29
.Dt I2C 8
30
.Dt I2C 8
30
.Os
31
.Os
31
.Sh NAME
32
.Sh NAME
Lines 33-39 Link Here
33
.Nd test I2C bus and slave devices
34
.Nd test I2C bus and slave devices
34
.Sh SYNOPSIS
35
.Sh SYNOPSIS
35
.Nm
36
.Nm
36
.Cm -a Ar address
37
.Cm -a|-A Ar address
37
.Op Fl f Ar device
38
.Op Fl f Ar device
38
.Op Fl d Ar r|w
39
.Op Fl d Ar r|w
39
.Op Fl w Ar 0|8|16
40
.Op Fl w Ar 0|8|16
Lines 41-46 Link Here
41
.Op Fl c Ar count
42
.Op Fl c Ar count
42
.Op Fl m Ar ss|rs|no
43
.Op Fl m Ar ss|rs|no
43
.Op Fl b
44
.Op Fl b
45
.Op Fl x
44
.Op Fl v
46
.Op Fl v
45
.Nm
47
.Nm
46
.Cm -s
48
.Cm -s
Lines 62-67 The options are as follows: Link Here
62
.Bl -tag -width ".Fl d Ar direction"
64
.Bl -tag -width ".Fl d Ar direction"
63
.It Fl a Ar address
65
.It Fl a Ar address
64
7-bit address on the I2C device to operate on (hex).
66
7-bit address on the I2C device to operate on (hex).
67
.It Fl A Ar address
68
8-bit address on the I2C device to operate on (hex).
65
.It Fl b
69
.It Fl b
66
binary mode - when performing a read operation, the data read from the device
70
binary mode - when performing a read operation, the data read from the device
67
is output in binary format on stdout; when doing a write, the binary data to
71
is output in binary format on stdout; when doing a write, the binary data to
Lines 87-92 offset within the device for data transfer (hex). Link Here
87
reset the controller.
91
reset the controller.
88
.It Fl s
92
.It Fl s
89
scan the bus for devices.
93
scan the bus for devices.
94
It outputs a table of all addresses. The content of each cell can have those meanings:
95
.Bl -bullet
96
.It
97
"--" No chip answered
98
.It
99
"UU" Chip is in use by a driver
100
.It
101
"XX" The address was skipped (see -n)
102
.It
103
An 7-bit address if a chip was found.
104
.El
105
.It Fl x
106
Use the I2CRDRW ioctl instead of the I2CREAD/I2CWRITE ones.
107
Some newer drivers only support this method.
90
.It Fl v
108
.It Fl v
91
be verbose.
109
be verbose.
92
.It Fl w Ar 0|8|16
110
.It Fl w Ar 0|8|16
(-)b/usr.sbin/i2c/i2c.c (-52 / +178 lines)
Lines 1-5 Link Here
1
/*-
1
/*-
2
 * Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka
2
 * Copyright (C) 2008-2009 Semihalf, Michal Hajduk and Bartlomiej Sieka
3
 * Copyright (C) 2015 Emmanuel Vadot <manu@bidouilliste.com>
3
 * All rights reserved.
4
 * All rights reserved.
4
 *
5
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * Redistribution and use in source and binary forms, with or without
Lines 57-62 struct options { Link Here
57
	int	reset;
58
	int	reset;
58
	int	mode;
59
	int	mode;
59
	char	dir;
60
	char	dir;
61
	char	rdrw;
60
	uint32_t	addr;
62
	uint32_t	addr;
61
	uint32_t	off;
63
	uint32_t	off;
62
};
64
};
Lines 71-77 usage(void) Link Here
71
{
73
{
72
74
73
	fprintf(stderr, "usage: %s -a addr [-f device] [-d [r|w]] [-o offset] "
75
	fprintf(stderr, "usage: %s -a addr [-f device] [-d [r|w]] [-o offset] "
74
	    "[-w [0|8|16]] [-c count] [-m [ss|rs|no]] [-b] [-v]\n",
76
	    "[-w [0|8|16]] [-c count] [-m [ss|rs|no]] [-b] [-x] [-v]\n",
75
	    getprogname());
77
	    getprogname());
76
	fprintf(stderr, "       %s -s [-f device] [-n skip_addr] -v\n",
78
	fprintf(stderr, "       %s -s [-f device] [-n skip_addr] -v\n",
77
	    getprogname());
79
	    getprogname());
Lines 119-129 skip_get_tokens(char *skip_addr, int *sk_addr, int max_index) Link Here
119
}
121
}
120
122
121
static int
123
static int
122
scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr)
124
scan_bus(struct iiccmd cmd, char rdrw, char *dev, int skip, char *skip_addr)
123
{
125
{
126
	struct iic_rdwr_data msg;
124
	struct skip_range addr_range = { 0, 0 };
127
	struct skip_range addr_range = { 0, 0 };
125
	int *tokens, fd, error, i, index, j;
128
	int *tokens, fd, error, index, i;
126
	int len = 0, do_skip = 0, no_range = 1;
129
	int len = 0, no_range = 1, row, col, addr, result;
130
	char buf = 0;
127
131
128
	fd = open(dev, O_RDWR);
132
	fd = open(dev, O_RDWR);
129
	if (fd == -1) {
133
	if (fd == -1) {
Lines 156-206 scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr) Link Here
156
		}
160
		}
157
	}
161
	}
158
162
159
	printf("Scanning I2C devices on %s: ", dev);
163
	msg.nmsgs = 1;
160
	for (i = 1; i < 127; i++) {
164
	if ((msg.msgs = calloc(1, sizeof(struct iic_msg))) == NULL)
161
165
		errx(1, "%s", strerror(errno));
162
		if (skip && ( addr_range.start < addr_range.end)) {
166
	msg.msgs->buf = &buf;
163
			if (i >= addr_range.start && i <= addr_range.end)
167
	msg.msgs->len = 1;
164
				continue;
168
	msg.msgs->flags = IIC_M_RD;
169
170
	printf("Scanning I2C devices on %s:\n", dev);
171
	printf("     0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F\n");
172
	for (row = 1; row < 8; row++) {
173
		printf("%02X:", row * 16);
174
		for (col = 0; col < 16; col++) {
175
			addr = (row * 16 + col);
176
			result = 0;
177
178
			if (skip && ( addr_range.start < addr_range.end)) {
179
				if (addr >= addr_range.start && addr <= addr_range.end) {
180
					printf(" XX");
181
					continue;
182
				}
165
183
166
		} else if (skip && no_range)
184
			} else if (skip && no_range)
167
			for (j = 0; j < index; j++) {
185
				for (i = 0; i < index; i++) {
168
				if (tokens[j] == i) {
186
					if (tokens[i] == (row * 16) + col) {
169
					do_skip = 1;
187
						printf(" XX");
170
					break;
188
						continue;
189
					}
171
				}
190
				}
172
			}
173
191
174
		if (do_skip) {
192
			if (rdrw) {
175
			do_skip = 0;
193
				msg.msgs->slave = addr << 1;
176
			continue;
194
				if (ioctl(fd, I2CRDWR, &msg) < 0)
195
					result = errno;
196
			} else {
197
				cmd.slave = addr << 1;
198
				cmd.last = 1;
199
				cmd.count = 0;
200
				if (ioctl(fd, I2CRSTCARD, &cmd) < 0)
201
					goto out;
202
203
				cmd.slave = addr << 1;
204
				cmd.last = 1;
205
				if (ioctl(fd, I2CSTART, &cmd) < 0)
206
					result = errno;
207
				cmd.slave = addr << 1;
208
				cmd.last = 1;
209
				ioctl(fd, I2CSTOP, &cmd);
210
			}
211
			switch (result) {
212
			case 0:
213
				printf(" %02X", addr);
214
				break;
215
			case EIO:
216
			case ENXIO:
217
			case ENOENT:
218
				printf(" --");
219
				break;
220
			case EBUSY:
221
				printf(" UU");
222
				break;
223
			default:
224
				printf("   ");
225
				break;
226
			}
177
		}
227
		}
178
228
		printf("\n");
179
		cmd.slave = i << 1;
180
		cmd.last = 1;
181
		cmd.count = 0;
182
		error = ioctl(fd, I2CRSTCARD, &cmd);
183
		if (error)
184
			goto out;
185
186
		cmd.slave = i << 1;
187
		cmd.last = 1;
188
		error = ioctl(fd, I2CSTART, &cmd);
189
		if (!error)
190
			printf("%x ", i);
191
		cmd.slave = i << 1;
192
		cmd.last = 1;
193
		error = ioctl(fd, I2CSTOP, &cmd);
194
	}
229
	}
195
	printf("\n");
230
	printf("\n");
196
231
197
	error = ioctl(fd, I2CRSTCARD, &cmd);
232
	if (!rdrw)
233
		error = ioctl(fd, I2CRSTCARD, &cmd);
198
out:
234
out:
199
	close(fd);
235
	close(fd);
200
	if (skip && no_range)
236
	if (skip && no_range)
201
		free(tokens);
237
		free(tokens);
202
238
203
	if (error) {
239
	if (rdrw)
240
		free(msg.msgs);
241
	
242
	if (!rdrw && error) {
204
		fprintf(stderr, "Error scanning I2C controller (%s): %s\n",
243
		fprintf(stderr, "Error scanning I2C controller (%s): %s\n",
205
		    dev, strerror(errno));
244
		    dev, strerror(errno));
206
		return (EX_NOINPUT);
245
		return (EX_NOINPUT);
Lines 465-470 err2: Link Here
465
	return (1);
504
	return (1);
466
}
505
}
467
506
507
static int
508
i2c_rdrw(char *dev, struct options i2c_opt, char *i2c_buf)
509
{
510
	struct iic_rdwr_data msgs;
511
	int fd, error, i;
512
	char *err_msg, ch;
513
514
	if (i2c_opt.dir == 'w') {
515
		if (i2c_opt.verbose && !i2c_opt.binary)
516
			fprintf(stderr, "Enter %u bytes of data: ", i2c_opt.count);
517
518
		for (i = 0; i < i2c_opt.count; i++) {
519
			ch = getchar();
520
			if (ch == EOF) {
521
				free(i2c_buf);
522
				err(1, "not enough data, exiting\n");
523
			}
524
			i2c_buf[i] = ch;
525
		}
526
	}
527
528
	fd = open(dev, O_RDWR);
529
	if (fd == -1)
530
		err(1, "open failed");
531
532
	msgs.nmsgs = 1;
533
	if (i2c_opt.width) {
534
		msgs.nmsgs = 2;
535
		msgs.msgs = calloc(2, sizeof(struct iic_msg));
536
		msgs.msgs[0].slave = i2c_opt.addr;
537
		msgs.msgs[0].len = i2c_opt.width / 8;
538
539
		if ((msgs.msgs[0].buf = calloc(msgs.msgs[0].len, sizeof(uint8_t))) == NULL) {
540
			err_msg = "can't malloc\n";
541
			goto err;
542
		}
543
		if (msgs.msgs[0].len == 1)
544
			msgs.msgs[0].buf[0] = i2c_opt.off & 0xff;
545
		else if (msgs.msgs[0].len == 2) {
546
			msgs.msgs[0].buf[0] = (i2c_opt.off >> 8) & 0xff;
547
			msgs.msgs[0].buf[1] = i2c_opt.off & 0xff;
548
		}
549
		if (msgs.msgs[0].buf == NULL) {
550
			err_msg = "error: offset malloc";
551
			goto err;
552
		}
553
554
		msgs.msgs[0].flags = IIC_M_WR;
555
		if (i2c_opt.mode == I2C_MODE_REPEATED_START || i2c_opt.mode == I2C_MODE_NONE)
556
			msgs.msgs[0].flags |= IIC_M_NOSTOP;
557
	}
558
559
	msgs.msgs[msgs.nmsgs - 1].slave = i2c_opt.addr;
560
	msgs.msgs[msgs.nmsgs - 1].len = i2c_opt.count;
561
	msgs.msgs[msgs.nmsgs - 1].buf = i2c_buf;
562
563
	if (i2c_opt.dir == 'r')
564
		msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_RD;
565
	else
566
		msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_WR;
567
568
	if (i2c_opt.mode == I2C_MODE_NONE)
569
		msgs.msgs[msgs.nmsgs - 1].flags |= IIC_M_NOSTART;
570
571
	error = ioctl(fd, I2CRDWR, &msgs);
572
	if (error == -1) {
573
		err_msg = "error sending i2c frame\n";
574
		goto err;
575
	}
576
577
	close(fd);
578
	return (0);
579
580
err:
581
	if (err_msg)
582
		fprintf(stderr, "%s", err_msg);
583
584
	close(fd);
585
	return (1);
586
}
587
468
int
588
int
469
main(int argc, char** argv)
589
main(int argc, char** argv)
470
{
590
{
Lines 493-503 main(int argc, char** argv) Link Here
493
	i2c_opt.skip = 0;	/* scan all addresses */
613
	i2c_opt.skip = 0;	/* scan all addresses */
494
	i2c_opt.reset = 0;	/* no bus reset */
614
	i2c_opt.reset = 0;	/* no bus reset */
495
	i2c_opt.mode = I2C_MODE_NOTSET;
615
	i2c_opt.mode = I2C_MODE_NOTSET;
616
	i2c_opt.rdrw = 0;	/* Use read/write by default */
496
617
497
	while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) {
618
	while ((ch = getopt(argc, argv, "a:A:f:d:o:w:c:m:n:sbvrhx")) != -1) {
498
		switch(ch) {
619
		switch(ch) {
499
		case 'a':
620
		case 'a':
500
			i2c_opt.addr = (strtoul(optarg, 0, 16) << 1);
621
		case 'A':
622
			if (i2c_opt.addr_set)
623
				usage();
624
			i2c_opt.addr = ch == 'a' ? (strtoul(optarg, 0, 16) << 1) : strtoul(optarg, 0, 16);
501
			if (i2c_opt.addr == 0 && errno == EINVAL)
625
			if (i2c_opt.addr == 0 && errno == EINVAL)
502
				i2c_opt.addr_set = 0;
626
				i2c_opt.addr_set = 0;
503
			else
627
			else
Lines 546-551 main(int argc, char** argv) Link Here
546
		case 'r':
670
		case 'r':
547
			i2c_opt.reset = 1;
671
			i2c_opt.reset = 1;
548
			break;
672
			break;
673
		case 'x':
674
			i2c_opt.rdrw = 1;
675
			break;
549
		case 'h':
676
		case 'h':
550
		default:
677
		default:
551
			usage();
678
			usage();
Lines 581-591 main(int argc, char** argv) Link Here
581
	if (i2c_opt.verbose)
708
	if (i2c_opt.verbose)
582
		fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, "
709
		fprintf(stderr, "dev: %s, addr: 0x%x, r/w: %c, "
583
		    "offset: 0x%02x, width: %u, count: %u\n", dev,
710
		    "offset: 0x%02x, width: %u, count: %u\n", dev,
584
		    i2c_opt.addr >> 1, i2c_opt.dir, i2c_opt.off,
711
		    i2c_opt.addr, i2c_opt.dir, i2c_opt.off,
585
		    i2c_opt.width, i2c_opt.count);
712
		    i2c_opt.width, i2c_opt.count);
586
713
587
	if (i2c_opt.scan)
714
	if (i2c_opt.scan)
588
		exit(scan_bus(cmd, dev, i2c_opt.skip, skip_addr));
715
		exit(scan_bus(cmd, i2c_opt.rdrw, dev, i2c_opt.skip, skip_addr));
589
716
590
	if (i2c_opt.reset)
717
	if (i2c_opt.reset)
591
		exit(reset_bus(cmd, dev));
718
		exit(reset_bus(cmd, dev));
Lines 594-612 main(int argc, char** argv) Link Here
594
	if (i2c_buf == NULL)
721
	if (i2c_buf == NULL)
595
		err(1, "data malloc");
722
		err(1, "data malloc");
596
723
597
	if (i2c_opt.dir == 'w') {
724
	if (i2c_opt.rdrw == 1) {
598
		error = i2c_write(dev, i2c_opt, i2c_buf);
725
		error = i2c_rdrw(dev, i2c_opt, i2c_buf);
599
		if (error) {
726
	} else {
600
			free(i2c_buf);
727
		if (i2c_opt.dir == 'w') {
601
			return (1);
728
			error = i2c_write(dev, i2c_opt, i2c_buf);
729
		} else if (i2c_opt.dir == 'r') {
730
			error = i2c_read(dev, i2c_opt, i2c_buf);
602
		}
731
		}
603
	}
732
	}
604
	if (i2c_opt.dir == 'r') {
733
	if (error) {
605
		error = i2c_read(dev, i2c_opt, i2c_buf);
734
		free(i2c_buf);
606
		if (error) {
735
		return (1);
607
			free(i2c_buf);
608
			return (1);
609
		}
610
	}
736
	}
611
737
612
	if (i2c_opt.verbose)
738
	if (i2c_opt.verbose)

Return to bug 198817