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) |