⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 zc030x_i2c.c

📁 Linux下USB接口的摄像头源码,很详细!对写USB接口驱动有很大帮助的
💻 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 + -