📄 zc030x_i2c.c
字号:
/* Implementation file for I2C reading *//* Zc030x -- Driver -- Zc030x *//* This file is under GPL *//* Copyright : Andrew Birkett Cyril Russo---------------------------------------*//* Include the header */#include "zc030x_i2c.h"/* Include bridge reading and writing */#include "zc030x_reg.h"/* Define the implementation *//* Init I2C register access */int zc030x_i2c_init(struct usb_device *udev, const I2CInitSequence * pSequence){ /* Declare return value */ int ret = 0; int out = I2C_OK; /* Declare return buffer */ unsigned char buf[4] = { 0,0,0,0 }; /* Declare iterator */ int i = 0; /* Check argument */ if (udev == NULL || pSequence == NULL) return I2C_Error; /* Debug this access */ PDEBUG(4, "<<< I2CREGINIT"); /* Okay, start the sequence */ for (; i < I2C_InitSequenceSize; i++) { if (pSequence->Direction[i]) { ret = zc030x_reg_read(udev, pSequence->Value[i], pSequence->Address[i], pSequence->ReturnSize[i]); if (ret == REG_Error) return I2C_Error; if ( pSequence->ReturnSize[i] && memcmp(&pSequence->ReturnValue[i], buf, pSequence->ReturnSize[i] < sizeof(buf) ? pSequence->ReturnSize[i] : sizeof(buf) ) != 0) out = I2C_Warning; } else { ret = zc030x_reg_write(udev, pSequence->Address[i], pSequence->Value[i]); if (ret == REG_Error) return I2C_Error; if ( pSequence->ReturnSize[i] && memcmp(&pSequence->ReturnValue[i], buf, pSequence->ReturnSize[i] < sizeof(buf) ? pSequence->ReturnSize[i] : sizeof(buf) ) != 0) out = I2C_Warning; } } /* Debug the output */ PDEBUG(4, ">>> I2CREGINIT : udev = %p, ret (%d)[%02X]", udev, out, buf[0]); /* Okay, return */ return out;}/* Try to read an I2C register */int zc030x_i2c_reg_read(struct usb_device *udev, __u16 addr, __u16 size){ /* Declare return value */ int ret = 0; /* Declare return buffer */ unsigned char buf[4] = { 0,0,0,0 }; /* Check argument */ if (udev == NULL) return I2C_Error; /* Debug this access */ PDEBUG(4, "<<< I2CREGREAD : udev = %p, addr %04X(%d)", udev, addr, size); /* Select the register now... */ ret = zc030x_reg_write(udev, ZR(I2CAddressSelect), addr); if (ret == REG_Error) return I2C_Error; /* Send the I2C read command */ ret = zc030x_reg_write(udev, ZR(I2CCommand), ZV(I2CRead)); if (ret == REG_Error) return I2C_Error; /* This code should return 0xaa in buf, ack the previous transfer */ ret = zc030x_reg_read(udev, ZR(I2CStatus), 0x0001, 1); if (ret == REG_Error) return I2C_Error; /* And read the value */ ret = zc030x_reg_read(udev, ZR(I2CRead), 0x0001, size); if (ret == REG_Error) return I2C_Error; /* Save ret */ buf[0] = ret & 0xFF; buf[1] = (ret >> 8) & 0xFF; buf[2] = (ret >> 16) & 0xFF; buf[3] = (ret >> 24) & 0xFF; /* Prepare for next transfer (reset ?) */ ret = zc030x_reg_read(udev, ZR(I2CReadACK), 0x0001, 1); if (ret == REG_Error) return I2C_Error; /* And then re-read the I2C sensor address ? */ ret = zc030x_reg_read(udev, ZR(CMOSSensorSelect), 0x0001, 1); if (ret == REG_Error) return I2C_Error; /* And then re-read the I2C sensor address ? */ ret = zc030x_reg_read(udev, ZR(CMOSSensorSelect), 0x0001, 1); if (ret == REG_Error) return I2C_Error; PDEBUG(4, ">>> I2CREGREAD : ret %d, value : %04X", ret, (buf[0]<<8)|(buf[1])); /* Return the read value */ /* The code below is endian-proof */ ret = buf[0] | (buf[1]<<8) | (buf[2]<<16) | (buf[3]<<24); return ret;}/* Try to write an I2C register */int zc030x_i2c_reg_write(struct usb_device *udev, __u16 addr, __u16 value){ /* Declare return value */ int ret = 0; /* Declare return buffer */ unsigned char buf[4] = { 0,0,0,0 }; /* Check argument */ if (udev == NULL) return I2C_Error; /* Debug this access */// PDEBUG(4, "<<< I2CREGWRITE : udev = %p, addr %04X, value %04X", udev, addr, value); /* Select the register now... */ ret = zc030x_reg_write(udev, ZR(I2CAddressSelect), addr); if (ret == REG_Error) return I2C_Error; /* And send the value to be written */ ret = zc030x_reg_write(udev, ZR(I2CSetValue), value); if (ret == REG_Error) return I2C_Error; /* Need to ack the transfer */ ret = zc030x_reg_write(udev, ZR(I2CWriteACK), 0x0000); if (ret == REG_Error) return I2C_Error; /* Send the I2C write command */ ret = zc030x_reg_write(udev, ZR(I2CCommand), ZV(I2CWrite)); if (ret == REG_Error) return I2C_Error; /* Need to ack the I2C transfer, should return 0xaa */ ret = zc030x_reg_read(udev, ZR(I2CStatus), 0x0001, 1); if (ret == REG_Error) return I2C_Error;// PDEBUG(4, ">>> I2CREGWRITE : (should be 0xAA) value : %02X", ret & 0xFF); /* Okay return */ return buf[0] == 0x00 ? I2C_OK : I2C_Warning;}/* Init I2C register access */int zc030x_i2c_start(struct usb_device *udev, const I2CInitSequence * pSequence, const __u8 addr){ /* Declare the test sequence */ I2CInitSequence TestSequence = * pSequence; /* Declare iterator */ int i = 1; /* This should starts from 1 */ /* Check argument */ if (udev == NULL || pSequence == NULL) return I2C_Error; /* Debug this access */ PDEBUG(2, "<<< I2CSTART"); /* Find the index of the access to register 0x010 on Zc chip */ while (i < I2C_InitSequenceSize && TestSequence.Address[i] != 0x10) i++; /* Not found, bad test sequence */ if (i == I2C_InitSequenceSize) return I2C_Error; /* Found */ /* Okay, start the sequence */ TestSequence.Value[i] = addr; /* Init the read with the test sequence */ if (zc030x_i2c_init(udev, &TestSequence) == I2C_Error) return I2C_Error; /* Okay, return */ return I2C_OK;}/* Init I2C register access */int zc030x_i2c_detect(struct usb_device *udev, const I2CInitSequence * pSequence){ /* Declare return value */ int out = I2C_OK; /* Declare return buffer */ unsigned char buf[8] = { 0,0,0,0,0,0,0,0 }; /* Declare the test sequence */ I2CInitSequence TestSequence = * pSequence; /* Declare iterator */ int i = 1; /* This should starts from 1 */ int index = 0; /* Check argument */ if (udev == NULL || pSequence == NULL) return I2C_Error; /* Debug this access */ PDEBUG(2, "<<< I2CREGDETECT"); /* Find the index of the access to register 0x010 on Zc chip */ while (i < I2C_InitSequenceSize && TestSequence.Address[i] != 0x10) i++; /* Not found, bad test sequence */ if (i == I2C_InitSequenceSize) return I2C_Error; /* Found */ index = i; PDEBUG(2, "I2CREGDETECT : index found is %d", index); /* Okay, start the sequence */ TestSequence.Value[index] = 0x00; while (!buf[0] && !buf[1] && !buf[2] && !buf[3] && !buf[4] && !buf[5] && !buf[6] && !buf[7] && TestSequence.Value[index] != 0x3f) { /* Init the read with the test sequence */ if (zc030x_i2c_init(udev, &TestSequence) == I2C_Error) out = I2C_Warning; /* Read the first 4 registers */ buf[0] = zc030x_i2c_reg_read(udev, 0, 1) & 0xFF; buf[1] = zc030x_i2c_reg_read(udev, 1, 1) & 0xFF; buf[2] = zc030x_i2c_reg_read(udev, 2, 1) & 0xFF; buf[3] = zc030x_i2c_reg_read(udev, 3, 1) & 0xFF; buf[4] = zc030x_i2c_reg_read(udev, 4, 1) & 0xFF; buf[5] = zc030x_i2c_reg_read(udev, 5, 1) & 0xFF; buf[6] = zc030x_i2c_reg_read(udev, 6, 1) & 0xFF; buf[7] = zc030x_i2c_reg_read(udev, 0x14, 1) & 0xFF; PDEBUG(2, "I2CREGDETECT : Current index is %d", TestSequence.Value[index]); TestSequence.Value[index] ++; } /* Save the test sequence */ if (TestSequence.Value[index] != 0x3f) { TestSequence.Value[index] --; /* TODO Make this possible */ //pSequence->Value[index] = TestSequence.Value[index]; } if (TestSequence.Value[index] != 0x3f) { PDEBUG(2, ">>> I2CREGDETECT : ret %d, sensor found at 0x%02X", out, TestSequence.Value[index]); } else { PDEBUG(2, ">>> I2CREGDETECT : ret %d, sensor not found in the range 0-FF", out); } return TestSequence.Value[index] + 1;}/* Check a sensor signature */int zc030x_i2c_checksignature(struct usb_device *udev, const signature * pSignature){ /* Declare return value */ int out = I2C_OK; /* Declare some buffer */ unsigned char buf[S_Length]; /* Declare iterator */ int i = 0; int index = 0; int error = 0; /* Check argument */ if (udev == NULL || pSignature == NULL) return I2C_Error; /* Debug this function */ PDEBUG(2, ">>> I2CCHECKSIG : checking signature for %08X", pSignature->sensor_id); /* If the signature doesn't exists */ if (!pSignature->signature_length) return 0; /* Read the signature */ for (i = 0; i < pSignature->signature_length; i++) { /* Read the specified register */ buf[i] = zc030x_i2c_reg_read(udev, pSignature->i2c_reg_addr[i], 1); /* Increment the error */ index += abs(buf[i] - pSignature->i2c_ro_value[i]); error += buf[i] < pSignature->i2c_ro_value[i] ? pSignature->i2c_ro_value[i] : buf[i]; /* Debug this */ PDEBUG(5, "DeltaSignature is %d [%02X %02X]", index, buf[i], pSignature->i2c_ro_value[i]); } /* Process the probabilities for this sensor to be the specified sensor */ /* The formula is very simple: */ /* P = 1 - Sum_of_all_errors / (The_Maximum_Possible_Error * Nb_Checks) */ /* So with integer, P = 1 - SOAE / (Accumulated Error) in [0 1] or */ /* P = 256 - SOAE * 256 / Error in [0 256] */ if (error) out = 256 - (index * 256) / (error); else out = 0; /* Make out be in [0;100] range */ out = out * 100 >> 8; PDEBUG(2, "<<< I2CCHECKSIG : probabilities for this sensor to be %08X : %d", pSignature->sensor_id, out); /* Okay, return */ return out;}/* Get a simple register map */int zc030x_i2c_simple_registermap(struct usb_device *udev){ /* Declare return value */ int out = I2C_OK; /* Declare return buffer */ unsigned char buf[4] = { 0,0,0,0 }; /* Declare iterator */ int i = 0; /* Debug level */ int _debug = debug; /* Check argument */ if (udev == NULL) return I2C_Error; /* Debug this access */ PDEBUG(2, "<<< I2CSREGMAP"); /* Decrease the debug level */ debug = 3; /* Okay, start the mapping */ for (; i < S_Length * 2; i++) { /* Read the first 4 registers */ buf[0] = zc030x_i2c_reg_read(udev, i, 1) & 0xFF; PDEBUG(2, " I2CSREGMAP : Read %02X @ %02X", buf[0], i); } /* Restore the debug level */ debug = _debug; /* Return */ PDEBUG(2, "<<< I2CSREGMAP"); return out;}/* Write an I2C config */int zc030x_i2c_writeconfig(struct usb_device *udev, const SensorConfig * pConfig){ /* Declare return value */ int out = I2C_OK; /* Declare iterator */ int i = 0; /* Check argument */ if (udev == NULL || pConfig == NULL) return I2C_Error; /* Debug this access */ PDEBUG(2, "<<< I2CWRITECONFIG"); for (i = 0; i < pConfig->Length; i++) { if (zc030x_i2c_reg_write(udev, pConfig->Addresses[i], pConfig->Values[i]) == I2C_Error) out = I2C_Warning; } /* Return */ PDEBUG(2, "<<< I2CWRITECONFIG"); return out;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -