1
1
hw/utils/i2c-scan/main.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);
}