237 строки
7.1 KiB
C
237 строки
7.1 KiB
C
/*
|
|
* I2C scan utility
|
|
*
|
|
* (c) 2015, SWD Embedded Systems Limited, http://www.kpda.ru
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <hw/i2c.h>
|
|
#include <stdint.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
|
|
|
|
#define REGISTER_SIZE_BYTES 1
|
|
|
|
#define UTILITY_MODE_RW 0
|
|
#define UTILITY_MODE_FIND 1
|
|
|
|
|
|
/* Devctl type SEND pointers: */
|
|
uint8_t *devctl_send_message; /* Pointer to devctl message */
|
|
uint8_t *register_send_dev_num; /* Pointer to register number in devctl message */
|
|
uint8_t *data_send; /* Pointer to data to send in devctl message */
|
|
i2c_send_t *send_header; /* Pointer to header */
|
|
|
|
/* Devctl type SEND-RECEIVE pointers: */
|
|
uint8_t *devctl_message; /* Pointer to devctl message */
|
|
i2c_sendrecv_t *send_receive_header; /* Pointer to header */
|
|
uint8_t *register_dev_num; /* Pointer to register number in devctl message */
|
|
uint8_t *data; /* Pointer to data to send in devctl message */
|
|
|
|
|
|
/* Desciption: Initialization global structures */
|
|
void i2c_init()
|
|
{
|
|
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
|
|
send_receive_header = (void *)devctl_message;
|
|
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
|
|
data = (uint8_t *)register_dev_num;
|
|
|
|
devctl_send_message = calloc( 1, sizeof( i2c_send_t ) + REGISTER_SIZE_BYTES + sizeof( uint16_t ) );
|
|
register_send_dev_num = ((uint8_t *)devctl_send_message + sizeof( i2c_send_t ));
|
|
data_send = (uint8_t *)((uint8_t *)register_send_dev_num + sizeof( *register_send_dev_num ));
|
|
send_header = (void *)devctl_send_message;
|
|
}
|
|
|
|
|
|
/*
|
|
* Desciption: Read value from I2C device
|
|
* Parameters: device_desc - opened file descriptior
|
|
* reg_num - register number into device
|
|
* addr - addr device in I2C bus
|
|
* Return:
|
|
* -1 - if error detected
|
|
* register value - if Ok
|
|
*/
|
|
int read_i2c_register( int device_desc, int reg_num, uint8_t addr )
|
|
{
|
|
int ret;
|
|
|
|
devctl_message = calloc( 1, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES );
|
|
send_receive_header = (void *)devctl_message;
|
|
register_dev_num = ((uint8_t *)devctl_message + sizeof( i2c_sendrecv_t ));
|
|
data = (uint8_t *)register_dev_num;
|
|
*register_dev_num = reg_num;
|
|
|
|
send_receive_header->slave.addr = addr;
|
|
send_receive_header->slave.fmt = I2C_ADDRFMT_7BIT;
|
|
send_receive_header->send_len = 1;
|
|
send_receive_header->stop = 1;
|
|
send_receive_header->recv_len = REGISTER_SIZE_BYTES;
|
|
ret = devctl( device_desc, DCMD_I2C_SENDRECV, devctl_message, sizeof( i2c_sendrecv_t ) + REGISTER_SIZE_BYTES, NULL );
|
|
if ( ret )
|
|
return (-1);
|
|
else
|
|
return *data;
|
|
}
|
|
|
|
|
|
/*
|
|
* Desciption: Write value to I2C device
|
|
* Parameters: device_desc - opened file descriptior
|
|
* reg_num - register number into device
|
|
* addr - addr device in I2C bus
|
|
* value - value to write
|
|
* Return:
|
|
* EXIT_FAILURE - error detected,
|
|
* 0 - if OK
|
|
*/
|
|
int write_i2c_register( int device_desc, int reg_num, uint8_t addr, uint16_t value )
|
|
{
|
|
int ret;
|
|
|
|
*register_send_dev_num = reg_num;
|
|
*((uint8_t *)data_send) = value;
|
|
|
|
send_header->slave.addr = addr;
|
|
send_header->slave.fmt = I2C_ADDRFMT_7BIT;
|
|
send_header->len = sizeof( *register_send_dev_num ) + sizeof( *data_send );
|
|
send_header->stop = 1;
|
|
|
|
delay( 10 );
|
|
ret = devctl( device_desc, DCMD_I2C_SEND, devctl_send_message, sizeof( i2c_send_t ) + send_header->len, NULL );
|
|
delay( 10 );
|
|
if ( ret )
|
|
{
|
|
fprintf( stderr, "Error writing to register %d device %d value 0x%X.(%s)\n", reg_num, addr, value, strerror( ret ) );
|
|
return (EXIT_FAILURE);
|
|
} else
|
|
return (0);
|
|
}
|
|
|
|
|
|
void scan_i2c( int fd )
|
|
{
|
|
int i, j;
|
|
|
|
fprintf( stderr, " 0 1 2 3 4 5 6 7 8 9 a b c d e f\n" );
|
|
|
|
for ( j = 0; j < 128; j += 16 )
|
|
{
|
|
fprintf( stderr, "%02x: ", j );
|
|
for ( i = 0; i < 16 ; i++ )
|
|
{
|
|
if ( read_i2c_register( fd, 0, i + j ) >= 0 )
|
|
fprintf( stderr, "%02x ", i + j );
|
|
else
|
|
fprintf( stderr, "-- " );
|
|
}
|
|
fprintf( stderr, "\n" );
|
|
}
|
|
}
|
|
|
|
|
|
int main( int argc, char **argv )
|
|
{
|
|
char *device_name = "/dev/i2c0";
|
|
int option,
|
|
device_desc = -1,
|
|
i,
|
|
write_value = -1,
|
|
utility_mode = UTILITY_MODE_FIND,
|
|
reg_num = 0,
|
|
addr = 0,
|
|
val,
|
|
register_count = 1;
|
|
|
|
while ( (option = getopt( argc, argv, "d:a:r:c:w:f" )) != -1 )
|
|
{
|
|
switch ( option )
|
|
{
|
|
case 'd':
|
|
device_name = optarg;
|
|
break;
|
|
|
|
case 'a':
|
|
addr = strtol( optarg, NULL, 0 );
|
|
utility_mode = UTILITY_MODE_RW;
|
|
break;
|
|
|
|
case 'r':
|
|
reg_num = strtol( optarg, NULL, 0 );
|
|
utility_mode = UTILITY_MODE_RW;
|
|
break;
|
|
|
|
case 'c':
|
|
register_count = strtol( optarg, NULL, 0 );
|
|
break;
|
|
|
|
case 'w':
|
|
write_value = strtol( optarg, NULL, 0 );
|
|
utility_mode = UTILITY_MODE_RW;
|
|
break;
|
|
|
|
case 'f':
|
|
utility_mode = UTILITY_MODE_FIND;
|
|
break;
|
|
|
|
default:
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
device_desc = open( device_name, O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO );
|
|
if ( device_desc < 0 )
|
|
{
|
|
perror( "Failed to open I2C device " );
|
|
return (-1);
|
|
}
|
|
|
|
i2c_init();
|
|
|
|
if ( utility_mode == UTILITY_MODE_FIND )
|
|
{
|
|
printf( "Scanning I2C device %s for I2C devices...\n", device_name );
|
|
scan_i2c( device_desc );
|
|
printf( "Scanning done \n" );
|
|
close( device_desc );
|
|
return (0);
|
|
}
|
|
|
|
printf( "I2C device 0x%X \n", addr );
|
|
for ( i = 0; i < register_count; i++ )
|
|
{
|
|
if ( write_value != -1 )
|
|
{
|
|
val = write_i2c_register( device_desc, reg_num + i, addr, write_value );
|
|
if ( !val )
|
|
printf( "Writing value 0x%X to register 0x%X\n", write_value, (reg_num + i) );
|
|
else {
|
|
fprintf( stderr, "Error writing device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
|
|
close( device_desc );
|
|
return (-1);
|
|
}
|
|
}
|
|
|
|
val = read_i2c_register( device_desc, reg_num + i, addr );
|
|
if ( val < 0 )
|
|
{
|
|
fprintf( stderr, "Error reading from device 0x%X register 0x%X: (%s)\n", addr, (reg_num + i), strerror( val ) );
|
|
close( device_desc );
|
|
return (-1);
|
|
} else
|
|
printf( "Reg[0x%02X] = 0x%X\n", reg_num + i, val );
|
|
}
|
|
|
|
close( device_desc );
|
|
|
|
return (0);
|
|
}
|