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, i, index, j; |
126 |
int len = 0, do_skip = 0, no_range = 1; |
129 |
int len = 0, do_skip = 0, no_range = 1; |
|
|
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-162
scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr)
Link Here
|
156 |
} |
160 |
} |
157 |
} |
161 |
} |
158 |
|
162 |
|
|
|
163 |
|
159 |
printf("Scanning I2C devices on %s: ", dev); |
164 |
printf("Scanning I2C devices on %s: ", dev); |
|
|
165 |
|
166 |
msg.nmsgs = 1; |
167 |
msg.msgs = calloc(1, sizeof(struct iic_msg)); |
168 |
msg.msgs->buf = &buf; |
169 |
msg.msgs->len = 1; |
170 |
msg.msgs->flags = IIC_M_RD; |
160 |
for (i = 1; i < 127; i++) { |
171 |
for (i = 1; i < 127; i++) { |
161 |
|
172 |
|
162 |
if (skip && ( addr_range.start < addr_range.end)) { |
173 |
if (skip && ( addr_range.start < addr_range.end)) { |
Lines 176-206
scan_bus(struct iiccmd cmd, char *dev, int skip, char *skip_addr)
Link Here
|
176 |
continue; |
187 |
continue; |
177 |
} |
188 |
} |
178 |
|
189 |
|
179 |
cmd.slave = i << 1; |
190 |
if (rdrw) { |
180 |
cmd.last = 1; |
191 |
msg.msgs->slave = i << 1; |
181 |
cmd.count = 0; |
192 |
error = ioctl(fd, I2CRDWR, &msg); |
182 |
error = ioctl(fd, I2CRSTCARD, &cmd); |
193 |
if (error != -1) |
183 |
if (error) |
194 |
printf("%x ", i); |
184 |
goto out; |
195 |
} else { |
|
|
196 |
cmd.slave = i << 1; |
197 |
cmd.last = 1; |
198 |
cmd.count = 0; |
199 |
error = ioctl(fd, I2CRSTCARD, &cmd); |
200 |
if (error) |
201 |
goto out; |
185 |
|
202 |
|
186 |
cmd.slave = i << 1; |
203 |
cmd.slave = i << 1; |
187 |
cmd.last = 1; |
204 |
cmd.last = 1; |
188 |
error = ioctl(fd, I2CSTART, &cmd); |
205 |
error = ioctl(fd, I2CSTART, &cmd); |
189 |
if (!error) |
206 |
if (!error) |
190 |
printf("%x ", i); |
207 |
printf("%x ", i); |
191 |
cmd.slave = i << 1; |
208 |
cmd.slave = i << 1; |
192 |
cmd.last = 1; |
209 |
cmd.last = 1; |
193 |
error = ioctl(fd, I2CSTOP, &cmd); |
210 |
error = ioctl(fd, I2CSTOP, &cmd); |
|
|
211 |
} |
194 |
} |
212 |
} |
195 |
printf("\n"); |
213 |
printf("\n"); |
196 |
|
214 |
|
197 |
error = ioctl(fd, I2CRSTCARD, &cmd); |
215 |
if (!rdrw) |
|
|
216 |
error = ioctl(fd, I2CRSTCARD, &cmd); |
198 |
out: |
217 |
out: |
199 |
close(fd); |
218 |
close(fd); |
200 |
if (skip && no_range) |
219 |
if (skip && no_range) |
201 |
free(tokens); |
220 |
free(tokens); |
202 |
|
221 |
|
203 |
if (error) { |
222 |
if (rdrw) |
|
|
223 |
free(msg.msgs); |
224 |
|
225 |
if (!rdrw && error) { |
204 |
fprintf(stderr, "Error scanning I2C controller (%s): %s\n", |
226 |
fprintf(stderr, "Error scanning I2C controller (%s): %s\n", |
205 |
dev, strerror(errno)); |
227 |
dev, strerror(errno)); |
206 |
return (EX_NOINPUT); |
228 |
return (EX_NOINPUT); |
Lines 465-470
err2:
Link Here
|
465 |
return (1); |
487 |
return (1); |
466 |
} |
488 |
} |
467 |
|
489 |
|
|
|
490 |
static int |
491 |
i2c_rdrw(char *dev, struct options i2c_opt, char *i2c_buf) |
492 |
{ |
493 |
struct iic_rdwr_data msgs; |
494 |
int fd, error, i; |
495 |
char *err_msg, ch; |
496 |
|
497 |
if (i2c_opt.dir == 'w') { |
498 |
if (i2c_opt.verbose && !i2c_opt.binary) |
499 |
fprintf(stderr, "Enter %u bytes of data: ", i2c_opt.count); |
500 |
|
501 |
for (i = 0; i < i2c_opt.count; i++) { |
502 |
ch = getchar(); |
503 |
if (ch == EOF) { |
504 |
free(i2c_buf); |
505 |
err(1, "not enough data, exiting\n"); |
506 |
} |
507 |
i2c_buf[i] = ch; |
508 |
} |
509 |
} |
510 |
|
511 |
fd = open(dev, O_RDWR); |
512 |
if (fd == -1) |
513 |
err(1, "open failed"); |
514 |
|
515 |
msgs.nmsgs = 1; |
516 |
if (i2c_opt.width) { |
517 |
msgs.nmsgs = 2; |
518 |
msgs.msgs = calloc(2, sizeof(struct iic_msg)); |
519 |
msgs.msgs[0].slave = i2c_opt.addr; |
520 |
msgs.msgs[0].len = i2c_opt.width / 8; |
521 |
|
522 |
if ((msgs.msgs[0].buf = calloc(msgs.msgs[0].len, sizeof(uint8_t))) == NULL) { |
523 |
err_msg = "can't malloc\n"; |
524 |
goto err; |
525 |
} |
526 |
if (msgs.msgs[0].len == 1) |
527 |
msgs.msgs[0].buf[0] = i2c_opt.off & 0xff; |
528 |
else if (msgs.msgs[0].len == 2) { |
529 |
msgs.msgs[0].buf[0] = (i2c_opt.off >> 8) & 0xff; |
530 |
msgs.msgs[0].buf[1] = i2c_opt.off & 0xff; |
531 |
} |
532 |
if (msgs.msgs[0].buf == NULL) { |
533 |
err_msg = "error: offset malloc"; |
534 |
goto err; |
535 |
} |
536 |
|
537 |
msgs.msgs[0].flags = IIC_M_WR; |
538 |
if (i2c_opt.mode == I2C_MODE_REPEATED_START || i2c_opt.mode == I2C_MODE_NONE) |
539 |
msgs.msgs[0].flags |= IIC_M_NOSTOP; |
540 |
} |
541 |
|
542 |
msgs.msgs[msgs.nmsgs - 1].slave = i2c_opt.addr; |
543 |
msgs.msgs[msgs.nmsgs - 1].len = i2c_opt.count; |
544 |
msgs.msgs[msgs.nmsgs - 1].buf = i2c_buf; |
545 |
|
546 |
if (i2c_opt.dir == 'r') |
547 |
msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_RD; |
548 |
else |
549 |
msgs.msgs[msgs.nmsgs - 1].flags = IIC_M_WR; |
550 |
|
551 |
if (i2c_opt.mode == I2C_MODE_NONE) |
552 |
msgs.msgs[msgs.nmsgs - 1].flags |= IIC_M_NOSTART; |
553 |
|
554 |
error = ioctl(fd, I2CRDWR, &msgs); |
555 |
if (error == -1) { |
556 |
err_msg = "error sending i2c frame\n"; |
557 |
goto err; |
558 |
} |
559 |
|
560 |
close(fd); |
561 |
return (0); |
562 |
|
563 |
err: |
564 |
if (err_msg) |
565 |
fprintf(stderr, "%s", err_msg); |
566 |
|
567 |
close(fd); |
568 |
return (1); |
569 |
} |
570 |
|
468 |
int |
571 |
int |
469 |
main(int argc, char** argv) |
572 |
main(int argc, char** argv) |
470 |
{ |
573 |
{ |
Lines 493-500
main(int argc, char** argv)
Link Here
|
493 |
i2c_opt.skip = 0; /* scan all addresses */ |
596 |
i2c_opt.skip = 0; /* scan all addresses */ |
494 |
i2c_opt.reset = 0; /* no bus reset */ |
597 |
i2c_opt.reset = 0; /* no bus reset */ |
495 |
i2c_opt.mode = I2C_MODE_NOTSET; |
598 |
i2c_opt.mode = I2C_MODE_NOTSET; |
|
|
599 |
i2c_opt.rdrw = 0; /* Use read/write by default */ |
496 |
|
600 |
|
497 |
while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrh")) != -1) { |
601 |
while ((ch = getopt(argc, argv, "a:f:d:o:w:c:m:n:sbvrhx")) != -1) { |
498 |
switch(ch) { |
602 |
switch(ch) { |
499 |
case 'a': |
603 |
case 'a': |
500 |
i2c_opt.addr = (strtoul(optarg, 0, 16) << 1); |
604 |
i2c_opt.addr = (strtoul(optarg, 0, 16) << 1); |
Lines 546-551
main(int argc, char** argv)
Link Here
|
546 |
case 'r': |
650 |
case 'r': |
547 |
i2c_opt.reset = 1; |
651 |
i2c_opt.reset = 1; |
548 |
break; |
652 |
break; |
|
|
653 |
case 'x': |
654 |
i2c_opt.rdrw = 1; |
655 |
break; |
549 |
case 'h': |
656 |
case 'h': |
550 |
default: |
657 |
default: |
551 |
usage(); |
658 |
usage(); |
Lines 585-591
main(int argc, char** argv)
Link Here
|
585 |
i2c_opt.width, i2c_opt.count); |
692 |
i2c_opt.width, i2c_opt.count); |
586 |
|
693 |
|
587 |
if (i2c_opt.scan) |
694 |
if (i2c_opt.scan) |
588 |
exit(scan_bus(cmd, dev, i2c_opt.skip, skip_addr)); |
695 |
exit(scan_bus(cmd, i2c_opt.rdrw, dev, i2c_opt.skip, skip_addr)); |
589 |
|
696 |
|
590 |
if (i2c_opt.reset) |
697 |
if (i2c_opt.reset) |
591 |
exit(reset_bus(cmd, dev)); |
698 |
exit(reset_bus(cmd, dev)); |
Lines 594-612
main(int argc, char** argv)
Link Here
|
594 |
if (i2c_buf == NULL) |
701 |
if (i2c_buf == NULL) |
595 |
err(1, "data malloc"); |
702 |
err(1, "data malloc"); |
596 |
|
703 |
|
597 |
if (i2c_opt.dir == 'w') { |
704 |
if (i2c_opt.rdrw == 1) { |
598 |
error = i2c_write(dev, i2c_opt, i2c_buf); |
705 |
error = i2c_rdrw(dev, i2c_opt, i2c_buf); |
599 |
if (error) { |
706 |
} else { |
600 |
free(i2c_buf); |
707 |
if (i2c_opt.dir == 'w') { |
601 |
return (1); |
708 |
error = i2c_write(dev, i2c_opt, i2c_buf); |
|
|
709 |
} else if (i2c_opt.dir == 'r') { |
710 |
error = i2c_read(dev, i2c_opt, i2c_buf); |
602 |
} |
711 |
} |
603 |
} |
712 |
} |
604 |
if (i2c_opt.dir == 'r') { |
713 |
if (error) { |
605 |
error = i2c_read(dev, i2c_opt, i2c_buf); |
714 |
free(i2c_buf); |
606 |
if (error) { |
715 |
return (1); |
607 |
free(i2c_buf); |
|
|
608 |
return (1); |
609 |
} |
610 |
} |
716 |
} |
611 |
|
717 |
|
612 |
if (i2c_opt.verbose) |
718 |
if (i2c_opt.verbose) |