Friday, August 3, 2018

ASUS BX32A R3010X Windows 8 1 32Bit 64it Driver

ASUS BX32A R3010X Windows 8 1 32Bit 64it Driver



      I2C (I Squared C) is a very common interface for controlling peripheral chip, lots sensor are based on this interface. Theoretically, it is necessary to write a driver for communicating with peripheral chip via I2C (it is typical bus driver). However, if the peripheral chip is specified for a application using, to understand the Linux driver model is a futile work but benefit is low. The driver model is a huge knowledge, it needs lots reading/searching/practicing to make the written driver stable.

     This post tries to resolve the pain : Someone could manipulate the peripheral chip but know nothing about Linux driver model.


   SHT20 :

      SHT10 is a very famous temperature and humidity sensor, it features high precision (with extravagant price ??) for industrial use. For the manufacturer has ploughed makers market, the example code for SHT10 is very common. However, most SHT10 module requires user to solder its pin, but I am a code worker instead of a soldering worker currently. Thus I buy the SHT20 module from Celestial Empires Alibaba with fixed pin to eschew the soldering work.

   ?.  Install the necessary i2c  kernel modules and tool , and to configure it to be usable.
My development board is OpenWRT, to install those, the most easy way is to via opkg commands:


opkg update
opkg install i2c-tools
opkg install kmod-i2c-gpio-custom kmod-i2c-core

After the installation has been done, it is time to load the i2c kernel module and to configure which pin would be serial data(SDA) and which would be serial clock (SCL). for me, I adopt GPIO 20 as SDA, and GPIO 19 as SCL, and I set this i2c device(SHT20) number is 0:

insmod i2c-dev
insmod i2c-gpio-custom bus0=0,20,19 #<ID>,<SDA>,<SCL>

This configure you need to refer to your circuit schematic. It is mine :


And the i2c would reveal under folder /dev :


root@GL-AR150:~# ls /dev/i2c-0 
/dev/i2c-0

But once you reboot your development board, the i2c would disappear, it is necessary to re-configure again (from insmod mode command). The way to configurate i2c once and for all is to add a file under folder /etc/modules.d/. The file is script essentially but the name could be of your preference.  For me, the file name is i2c,  the content is

root@GL-AR150:~# cat /etc/modules.d/i2c 
i2c-dev
i2c-gpio-custom bus0=0,20,19

That is the commands I typed but leaves out "inmod.

The files under the /etc/modules.d/ would be run one by one to load the kernel modules (drivers).

If you want to configurate multi i2c device, the commands should be (take 2 as example)

insmod i2c-gpio-custom bus0=0,20,19 bus1=1,18,21
 
And the autoloaded module script content in /etc/modules.d/i2c is :
 
i2c-gpio-custom bus0=0,20,19 bus1=1,18,21

i2c-gpio-custom is a kernel module, you could not insert that into kernel twice.




 ?. Check the SHT20 has connected to the linux device:
The tool has been prepared in most busybox especially the okpg has installed it. Type the following command to probe if there device under i2c-0 :


root@GL-AR150:~# i2cdetect 0
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-0.
I will probe address range 0x03-0x77.
Continue? [Y/n] y
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --


There report means there is a i2c slave in the address 0x40, and refer to SHT20 datasheet, The default SHT20 i2c address is 0x40 indeedly  : in SHT20 datasheet page 7/4, session 5.3 : After  sending  the  Start condition,  the  subsequent  I2C header consists of the 7bit I2C device address �1000�000� and an SDA direction bit (Read R: �1�, Write W: �0�). the value 0b0100 000 in binary is 0x40 in heximal.

 ?. Prepare a header for i2c manipulations.



      Header i2c-dev.h is a header for application to manipulation the i2c peripheral  in the form of /dev/i2c-X, the application could access i2c peripheral without specified device-driver support. I do not write the SHT20 driver, so it is necessary for me.

     In OpenWRT (maybe for  Raspberry pi is the same), the i2c-dev.h is not complete: in the OpenWRT, the header is like this, compared with the complete version, the inline functions do not exist. Thus it is requisite  to replenish the header, I name the header as openwrt_i2c-dev.h.


#ifndef _OPENWRT_I2C_DEV_H_
#define _OPENWRT_I2C_DEV_H_

#include <linux/types.h>
#include <linux/i2c.h>

#include <sys/ioctl.h>


#ifdef __cplusplus
extern "C" {
#endif

static inline __s32 i2c_smbus_access(int file, char read_write, __u8 command,
int size, union i2c_smbus_data *data)
{
struct i2c_smbus_ioctl_data args;

args.read_write = read_write;
args.command = command;
args.size = size;
args.data = data;
return ioctl(file,I2C_SMBUS,&args);
}


static inline __s32 i2c_smbus_write_quick(int file, __u8 value)
{
return i2c_smbus_access(file,value,0,I2C_SMBUS_QUICK,NULL);
}

static inline __s32 i2c_smbus_read_byte(int file)
{
union i2c_smbus_data data;
if (i2c_smbus_access(file,I2C_SMBUS_READ,0,I2C_SMBUS_BYTE,&data))
return -1;
else
return 0x0FF & data.byte;
}

static inline __s32 i2c_smbus_write_byte(int file, __u8 value)
{
return i2c_smbus_access(file,I2C_SMBUS_WRITE,value,
I2C_SMBUS_BYTE,NULL);
}

static inline __s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
I2C_SMBUS_BYTE_DATA,&data))
return -1;
else
return 0x0FF & data.byte;
}

static inline __s32 i2c_smbus_write_byte_data(int file, __u8 command,
__u8 value)
{
union i2c_smbus_data data;
data.byte = value;
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_BYTE_DATA, &data);
}

static inline __s32 i2c_smbus_read_word_data(int file, __u8 command)
{
union i2c_smbus_data data;
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
I2C_SMBUS_WORD_DATA,&data))
return -1;
else
return 0x0FFFF & data.word;
}

static inline __s32 i2c_smbus_write_word_data(int file, __u8 command,
__u16 value)
{
union i2c_smbus_data data;
data.word = value;
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_WORD_DATA, &data);
}

static inline __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
{
union i2c_smbus_data data;
data.word = value;
if (i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_PROC_CALL,&data))
return -1;
else
return 0x0FFFF & data.word;
}


/* Returns the number of read bytes */
static inline __s32 i2c_smbus_read_block_data(int file, __u8 command,
__u8 *values)
{
union i2c_smbus_data data;
int i;
if (i2c_smbus_access(file,I2C_SMBUS_READ,command,
I2C_SMBUS_BLOCK_DATA,&data))
return -1;
else {
for (i = 1; i <= data.block[0]; i++)
values[i-1] = data.block[i];
return data.block[0];
}
}

static inline __s32 i2c_smbus_write_block_data(int file, __u8 command,
__u8 length, __u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_BLOCK_DATA, &data);
}

static inline __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command,
__u8 length, __u8 *values)
{
union i2c_smbus_data data;
int i;
if (length > 32)
length = 32;
for (i = 1; i <= length; i++)
data.block[i] = values[i-1];
data.block[0] = length;
return i2c_smbus_access(file,I2C_SMBUS_WRITE,command,
I2C_SMBUS_I2C_BLOCK_DATA, &data);
}

#ifdef __cplusplus
}
#endif

#endif/*_OPENWRT_I2C_DEV_H_*/



?. The application for fetch data from SHT20.

The code be :


#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#include <unistd.h>

#include <sys/time.h>

#include <fcntl.h>
#include <sys/ioctl.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <errno.h>


#include "openwrt_i2c-dev.h"

#define MAX_STR_LEN (256)


int SeekI2CAddress(const char *p_device_name, int *p_i2c_device_address)
{
int i;
int fd;

fd = open(p_device_name, O_RDWR);
if(0 > fd)
{
printf("%s could not been open ", p_device_name);
return -1;
}

for(i = 3; i< 128; i++){
int status;
status = ioctl(fd, I2C_SLAVE, (void*)(intptr_t)i);

if (0 > status)
{
if (errno == EBUSY) {
printf(link download