i2c-api.c 4.89 KB
//------------------------------------------------------------------------------
// 
// 파 일 : i2c_api.c 
// 설 명 : I2C DEVICE DRIVE API LIB
//
// 작 성 : 유영창 frog@falinux.com
//------------------------------------------------------------------------------
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>

#include <linux/types.h>

#include <i2c-api.h>

//------------------------------------------------------------------------------
// 설명 : 매크로 상수 

#define I2C_MAX_BUS           8

//------------------------------------------------------------------------------
// 설명 : 전역변수

static i2c_bus_t ds[I2C_MAX_BUS];  // I2C 디바이스 드라이버 관리 구조체 
static int       i2c_bus_cnt = 0;     // 시스템에 존재하는 I2C 버스 수 

//------------------------------------------------------------------------------
// 설명 : pcmcia 디바이스 드라이버 주번호를 얻는다. 
// 매계 : major : 함수 실행 성공시 주번호를 전달한다. 
// 반환 : I2C_OK              : major 번호를 얻었다. 
//        I2C_NOT_FIND_MAJOR  : major 번호를 발견하지 못했다.
// 주의 : 
//------------------------------------------------------------------------------
int  i2c_get_major_i2c( int *major )
{
    FILE *fp;
    char  linebuff[128];
    char  device_name[32];
    int   tmp_major;
    
    fp = fopen("/proc/devices", "r");
    if(fp == NULL) 	return I2C_NOT_FIND_MAJOR;

    while(1) 
    {
        if( fgets(linebuff, sizeof( linebuff) , fp ) == NULL ) break;
  	    if (sscanf(linebuff, "%d %s", &tmp_major, device_name) == 2)
        {
	        if (strcmp("i2c", device_name) == 0)
            {
                *major    =  tmp_major;
                fclose( fp );   
                return I2C_NO_ERROR;
            } 
        }
    }
    fclose( fp );

    return I2C_NOT_FIND_MAJOR;
}

//------------------------------------------------------------------------------
// 설명 : I2C 버스 디바이스 파일을 만들고 연다.
//------------------------------------------------------------------------------
int i2c_make_bus_node( int major, int bn )
{
    sprintf(ds[bn].node_fname, "/dev/i2cbus%d-%d", getpid(), bn );
    mknod(ds[bn].node_fname, (S_IRWXU|S_IRWXG|S_IFCHR), (major<<8) + bn );
    ds[bn].fd = open(ds[bn].node_fname, O_RDWR );
//    printf( "%s ds[%d].fd = %d\n", ds[bn].node_fname, bn, ds[bn].fd );
    unlink(ds[bn].node_fname);
    return ds[bn].fd;
}

//------------------------------------------------------------------------------
// 설명 : I2C API 를 초기화 한다. 
//------------------------------------------------------------------------------
int i2c_init( void )
{
    int major;
    int ret;
    int lp;


    ret = i2c_get_major_i2c( &major );
    if( I2C_NOT_FIND_MAJOR == ret )
    {
    	printf( "can't find nodfile\n" );
    	return -1;
    }
     
    //printf( "I2C Major Numner = %d\n", major );

    i2c_bus_cnt = 0; 
    for( lp = 0; lp < I2C_MAX_BUS; lp++ )
    {
        if( i2c_make_bus_node( major, lp ) >= 0 )
        {
            i2c_bus_cnt++;
        } 
        else
        {
            ds[lp].fd  = -1;
        }
    }

    return 0;
}


//------------------------------------------------------------------------------
// 설명 : 현재 존재하는 I2C BUS 수를 얻는다. 
// 반환 : 소켓 수 
//------------------------------------------------------------------------------
int i2c_get_bus_count( void )
{
    return i2c_bus_cnt;
}

//------------------------------------------------------------------------------
// 설명 : I2C 버스에서 읽는다. 
//------------------------------------------------------------------------------
int i2c_read_data( access_data_t * access_data )
{
    if( ds[access_data->bus].fd < 0 ) return I2C_NOT_FIND_BUS;

    if( access_data->size > sizeof( access_data->data ) ) access_data->size = sizeof( access_data->data ); 

    ioctl( ds[access_data->bus].fd, I2C_SLAVE, access_data->addr ); 
    access_data->size = read( ds[access_data->bus].fd, access_data->data, access_data->size  );
    if( access_data->size < 0 ) return I2C_READ_DEVICE;

    return I2C_NO_ERROR; 
}

//------------------------------------------------------------------------------
// 설명 : I2C 버스에 데이터를 써 넣는다.
//------------------------------------------------------------------------------
int i2c_write_data( access_data_t * access_data )
{
    if( ds[access_data->bus].fd < 0 ) return I2C_NOT_FIND_BUS;

    if( access_data->size > sizeof( access_data->data ) ) access_data->size = sizeof( access_data->data );

    ioctl( ds[access_data->bus].fd, I2C_SLAVE, access_data->addr ); 
    access_data->size = write( ds[access_data->bus].fd, access_data->data, access_data->size  );
    if( access_data->size < 0 ) return I2C_WRITE_DEVICE;


    return I2C_NO_ERROR; 
}