mx53 camera s5k5bbgx驱动分析


一: linux驱动层

1.  通讯方式I2C驱动注册:

a: arch/arm/mach-mx5/mx53_xx.c

/*

声明s5k5bbgx的IIC 资源

*/

static int mxc_camera2_pwdn(int pwdn)
{
    if (pwdn)
        gpio_direction_output(MX53_HMS_CAMERA2_PWN, 1);
    else
        gpio_direction_output(MX53_HMS_CAMERA2_PWN, 0);
    return 0;
}    
 
static struct mxc_camera_platform_data camera2_data = {
    .mclk = 24000000,
    .csi = 0,
    .pwdn = mxc_camera2_pwdn,
}; 

static struct i2c_board_info mxc_i2c0_board_info[] __initdata = {

   {
    .type = "s5k5bbgx",
    .addr = 0x2d, 
      // IIC 地址为7位,最后一位是读写位,mx53的驱动内部会把地址左移一位,所以这里要右移一位
      .platform_data = (void *)&camera2_data,
     },

}

/*!
 * Board specific initialization.
 */
static void __init mxc_board_init(void)
{
i2c_register_board_info(0, mxc_i2c0_board_info,
                ARRAY_SIZE(mxc_i2c0_board_info));
}

b: driver/media/video/capture/xx_cam_2M.c

/*

*  注册IIC驱动

*/

static struct i2c_client *s5k5bbgx_i2c_client = NULL;


static const struct i2c_device_id s5k5bbgx_id[] = {
    {"s5k5bbgx", 0},
    {},
};

MODULE_DEVICE_TABLE(i2c, s5k5bbgx_id);

static struct 2055_i2c_drvier {
     .driver = {
          .owner = THIS_MODULE,
          .name  = "s5k5bbgx",
          },
    .probe  = s5k5bbgx_probe,
    .remove = s5k5bbgx_remove,
    .id_table = s5k5bbgx_id,


};
/*!
 * s5k5bbgx init function
 * Called by insmod s5k5bbgx_camera.ko.
 *
 * @return  Error code indicating success or failure
 */
static __init int s5k5bbgx_init(void)
{
    U8 err;
    err = i2c_add_driver(s5k5bbgx_i2c_driver);
    return err;
}
static int s5k5bbgx_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
{
    s5k5bbgx_i2c_client = client;

    return 0;
}
/*
 IIC 读写
*/
static s32 s5k5bbgx_read_reg(u16 reg, u16 *val)
{
        u8 au8RegBuf[2] = {0};
    u8 data[2] = {0};

        au8RegBuf[0] = reg >> 8;
        au8RegBuf[1] = reg & 0xff;

    if (2 != i2c_master_send(s5k5bbgx_i2c_client, au8RegBuf, 2)) {
                pr_err("%s:write reg error:reg=%x\n",
                                __func__, reg);
                return -1;
        }

    if (2 != i2c_master_recv(s5k5bbgx_i2c_client, data, 2)) {
                pr_err("%s:read reg error:reg=0x%04x\n",
                                __func__, reg);
                return -2;
        }

        *val = (data[0] << 8) | data[1];

        return 0;
}


static s32 s5k5bbgx_write_reg(u16 cammand, u16 val)
{
        u8 au8Buf[4] = {0};

    au8Buf[0] = cammand >> 8;
        au8Buf[1] = cammand & 0xff;
        au8Buf[2] = val >> 8;
        au8Buf[3] = val & 0xff;

    if (4 != i2c_master_send(s5k5bbgx_i2c_client, au8Buf, 4)) {
        pr_err("%s:write cammand error:cammand=0x%04x,val=0x%04x\n",
                __func__, cammand, val);
        return -1;
    }

    return 0;
}

至此IIC注册完毕

b: 注册 v4l2 slave device:

/*!
 * Maintains the information on the current state of the sesor.
 */
struct sensor {
    const struct mxc_camera_platform_data *platform_data;
    struct v4l2_int_device *v4l2_int_device;
    struct i2c_client *i2c_client;
    struct v4l2_pix_format pix;
    struct v4l2_captureparm streamcap;
    bool on;

    /* control settings */
    int brightness;
    int hue;
    int contrast;
    int saturation;
    int red;
    int green;
    int blue;
    int ae_mode;

    u32 mclk;
    int csi;
}s5k5bbgx_data;
/*!
 * This structure defines all the ioctls for this module and links them to the
 * enumeration.
 */
static struct v4l2_int_ioctl_desc s5k5bbgx_ioctl_desc[] = {
   
    {vidioc_int_s_parm_num, (v4l2_int_ioctl_func*)ioctl_s_parm},
    {vidioc_int_s_ctrl_num, (v4l2_int_ioctl_func*)ioctl_s_ctrl},
   
};


static struct v4l2_int_slave s5k5bbgx_slave = {
    .ioctls = s5k5bbgx_ioctl_desc,
    .num_ioctls = ARRAY_SIZE(s5k5bbgx_ioctl_desc),
};


static struct v4l2_int_device s5k5bbgx_int_device = {
    .module = THIS_MODULE,
    .name = "s5k5bbgx",
    .type = v4l2_int_type_slave,
    .u = {
        .slave = &s5k5bbgx_slave,
    },
};
/*!
 * ioctl_s_parm - V4L2 sensor interface handler for VIDIOC_S_PARM ioctl
 * @s: pointer to standard V4L2 device structure
 * @a: pointer to standard V4L2 VIDIOC_S_PARM ioctl structure
 *
 * Configures the sensor to use the input parameters, if possible.  If
 * not possible, reverts to the old parameters and returns the
 * appropriate error code.
 */
static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
    struct sensor *sensor = s->priv;
    struct v4l2_fract *timeperframe = &a->parm.capture.timeperframe;
    u32 tgt_fps;    /* target frames per secound */
    enum s5k5bbgx_frame_rate frame_rate;
    int ret = 0;

    /* Make sure power on */
    if (camera_plat->pwdn)
        camera_plat->pwdn(0);

    switch (a->type) {
    /* This is the only case currently handled. */
    case V4L2_BUF_TYPE_VIDEO_CAPTURE:


    /* These are all the possible cases. */
    case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    case V4L2_BUF_TYPE_VIDEO_OVERLAY:
    case V4L2_BUF_TYPE_VBI_CAPTURE:
    case V4L2_BUF_TYPE_VBI_OUTPUT:
    case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
    case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
        pr_debug("   type is not " \
            "V4L2_BUF_TYPE_VIDEO_CAPTURE but %d\n",
            a->type);
        ret = -EINVAL;
        break;

    default:
        pr_debug("   type is unknown - %d\n", a->type);
        ret = -EINVAL;
        break;
    }

    return ret;
}
/*!
 * ioctl_s_ctrl - V4L2 sensor interface handler for VIDIOC_S_CTRL ioctl
 * @s: pointer to standard V4L2 device structure
 * @vc: standard V4L2 VIDIOC_S_CTRL ioctl structure
 *
 * If the requested control is supported, sets the control's current
 * value in HW (and updates the video_control[] array).  Otherwise,
 * returns -EINVAL if the control is not supported.
 */
static int ioctl_s_ctrl(struct v4l2_int_device *s, struct v4l2_control *vc)
{
    int retval = 0;

    pr_debug("In s5k5bbgx:ioctl_s_ctrl %d\n",
         vc->id);

    switch (vc->id) {
    case V4L2_CID_BRIGHTNESS:
        break;
    case V4L2_CID_CONTRAST:
        break;
    case V4L2_CID_SATURATION:
        break;
    case V4L2_CID_HUE:
        break;
    case V4L2_CID_AUTO_WHITE_BALANCE:
        break;
    case V4L2_CID_DO_WHITE_BALANCE:
        break;
  default:
        retval = -EPERM;
        break;
    }

    return retval;
}



static int s5k5bbgx_probe(strct i2c_client *client, const struct i2c_device_id *id)
{
    s5k5bbgx_int_device.priv = &s5k5bbgx_data;
    retval = v4l2_int_device_register(&s5k5bbgx_int_device);
}
v4l2 slave device 注册完毕

c: s5k5bbgx 初始化和操作

static int s5k5bbgx_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
{

    /*
     * 默认的参数: yuv模式,像素,帧速等。这些参数会在s_param ioctl中重新设置
    */
    s5k5bbgx_data.pix.pixelformat = V4L2_PIX_FMT_YUYV;

    s5k5bbgx_data.pix.width = 800;
    s5k5bbgx_data.pix.height = 600;
    s5k5bbgx_data.streamcap.capability = V4L2_MODE_HIGHQUALITY |
                       V4L2_CAP_TIMEPERFRAME;
    s5k5bbgx.streamcap.capturemode = 0;
    s5k5bbgx_data.streamcap.timeperframe.denominator = DEFAULT_FPS;
    s5k5bbgx_data.streamcap.timeperframe.numerator = 1;

}
static int s5k5bbgx_init_mode(enum s5k5bbgx_frame_rate frame_rate,
                enum s5k5bbgx_mode mode)
{
  struct reg_value *pModeSetting = NULL;
    s32 i = 0;
    s32 iModeSettingArySize = 0;
    register u32 Delay_ms = 0;
    register u16 RegAddr = 0;
    register u8 Mask = 0;
    register u16 Val = 0;
    register u8 u8Val = 0;
    u8 RegVal = 0;
    int retval = 0;


     pModeSetting = s5k5bbgx_mode_info_data[frame_rate][mode].init_data_ptr;
     iModeSettingArySize = s5k5bbgx_mode_info_data[frame_rate][mode].init_data_size;                
     s5k5bbgx_data.pix.width = s5k5bbgx_mode_info_data[frame_rate][mode].width;
     s5k5bbgx_data.pix.height = s5k5bbgx_mode_info_data[frame_rate][mode].height;
     /*
     *  设置camera的参数,如fps,像素等
     */
    for (i = 0; i < iModeSettingArySize; ++i, ++pModeSetting) {
        Delay_ms = pModeSetting->u32Delay_ms;
        RegAddr = pModeSetting->u16RegAddr;
        Val = pModeSetting->u16Val;
        Mask = pModeSetting->u8Mask;
        if (Mask) {
            RegVal &= ~(u8)Mask;
            Val &= Mask;
            Val |= RegVal;
        }
        retval = s5k5bbgx_write_reg(RegAddr, Val);
        if (retval < 0)
            goto err;

        if (Delay_ms)
            msleep(Delay_ms);
    }
}

struct s5k5ggbx_set s5k5ggbx_set_data[12] = {
    {preview, ARRAY_SIZE(preview)}, //screen mode: auto
    {record, ARRAY_SIZE(record)},
    {night, ARRAY_SIZE(night)},
    {capture, ARRAY_SIZE(capture)}, //capture
    {normal, ARRAY_SIZE(normal)},   //color effect
    {mono, ARRAY_SIZE(mono)},
    {negative, ARRAY_SIZE(negative)},
    {sepia, ARRAY_SIZE(sepia)},
    {Auto, ARRAY_SIZE(Auto)},   //white balance
    {incandescent, ARRAY_SIZE(incandescent)},
    {daylight, ARRAY_SIZE(daylight)},
    {flourescent, ARRAY_SIZE(flourescent)}
};

/*
设置白平衡等参数
*/
static int s5k5ggbx_set_code(int index)
{
        struct reg_value *p = NULL;
        s32 i = 0;
        s32 size = 0;
        int retval;
        register u32 Delay_ms = 0;
        register u16 RegAddr = 0;
        register u16 Val = 0;

    p = s5k5ggbx_set_data[index].init_data_ptr;
    size = s5k5ggbx_set_data[index].init_data_size;

    for (i = 0; i < size; ++i, ++p) {
                Delay_ms = p->u32Delay_ms;
                RegAddr = p->u16RegAddr;
                Val = p->u16Val;

                retval = s5k5bbgx_write_reg(RegAddr, Val);
                if (retval < 0)
                    return retval;

                if (Delay_ms)
                        msleep(Delay_ms);

        }

        return 0;
}


static int ioctl_s_parm(struct v4l2_int_device *s, struct v4l2_streamparm *a)
{
 switch (a->type) {
    /* This is the only case currently handled. */
    case V4L2_BUF_TYPE_VIDEO_CAPTURE:
        /* Check that the new frame rate is allowed. */
        if ((timeperframe->numerator == 0) ||
            (timeperframe->denominator == 0)) {
            timeperframe->denominator = DEFAULT_FPS;
            timeperframe->numerator = 1;
        }

        tgt_fps = timeperframe->denominator /
              timeperframe->numerator;

        if (tgt_fps > MAX_FPS) {
            timeperframe->denominator = MAX_FPS;
            timeperframe->numerator = 1;
        } else if (tgt_fps < MIN_FPS) {
            timeperframe->denominator = MIN_FPS;
            timeperframe->numerator = 1;
        }

        /* Actual frame rate we use */
        tgt_fps = timeperframe->denominator /
              timeperframe->numerator;

        /* Actual frame rate we use */
        tgt_fps = timeperframe->denominator /
              timeperframe->numerator;

        if (tgt_fps == 15)
            frame_rate = ov2655_15_fps;
        else if (tgt_fps == 30)
            frame_rate = ov2655_30_fps;
        else if (tgt_fps == 7)
            frame_rate = ov2655_7p5_fps;
        else {
            pr_err(" The camera frame rate is not supported!\n");
            return -EINVAL;
        }

 sensor->streamcap.timeperframe = *timeperframe;
        sensor->streamcap.capturemode = (u32)a->parm.capture.capturemode;
printk("\n%s, frame_rate = %d, sensor->streamcap.capturemode = %d\n", __func__, frame_rate, sensor->streamcap.capturemode);
        if (sensor->streamcap.capturemode == 2) //preview: normal
         {
               s5k5ggbx_init_mode(frame_rate, sensor->streamcap.capturemode);
               s5k5ggbx_set_code(0);
         }
         else if (sensor->streamcap.capturemode == 4)    //capture
         {
                 s5k5ggbx_init_mode(frame_rate, sensor->streamcap.capturemode);
                s5k5ggbx_set_code(3);
         }
         else if (sensor->streamcap.capturemode == 1)    //preview: recording
         {
                s5k5ggbx_init_mode(frame_rate, sensor->streamcap.capturemode);
                s5k5ggbx_set_code(1);
         }


        break;

   }

}



二,V4L2 capture应用

1.接口

namespace android{

    class V4l2CapDeviceBase : public CaptureDeviceInterface{
    public:

        virtual CAPTURE_DEVICE_ERR_RET SetDevName(char * deviceName);
        virtual CAPTURE_DEVICE_ERR_RET GetDevName(char * deviceName);
        virtual CAPTURE_DEVICE_ERR_RET DevOpen();
        virtual CAPTURE_DEVICE_ERR_RET EnumDevParam(DevParamType devParamType, void *retParam);
        virtual CAPTURE_DEVICE_ERR_RET DevSetCtrl(int id,int value);
        virtual CAPTURE_DEVICE_ERR_RET DevSetConfig(struct capture_config_t *pCapcfg);
        virtual CAPTURE_DEVICE_ERR_RET DevAllocateBuf(DMA_BUFFER *DevBufQue, unsigned int *pBufQueNum);
        virtual CAPTURE_DEVICE_ERR_RET DevPrepare();
        virtual CAPTURE_DEVICE_ERR_RET DevStart();
        virtual CAPTURE_DEVICE_ERR_RET DevDequeue(unsigned int *pBufQueIdx);
 virtual CAPTURE_DEVICE_ERR_RET DevStop();
        virtual CAPTURE_DEVICE_ERR_RET DevDeAllocate();
        virtual CAPTURE_DEVICE_ERR_RET DevClose();

    protected:

        V4l2CapDeviceBase();
        virtual ~V4l2CapDeviceBase();
        virtual CAPTURE_DEVICE_ERR_RET V4l2Open();
        virtual CAPTURE_DEVICE_ERR_RET V4l2EnumParam(DevParamType devParamType, void *retParam);
        virtual CAPTURE_DEVICE_ERR_RET V4l2EnumFmt(void *retParam);
        virtual CAPTURE_DEVICE_ERR_RET V4l2EnumSizeFps(void *retParam);
        virtual CAPTURE_DEVICE_ERR_RET V4l2SetConfig(struct capture_config_t *pCapcfg);
        virtual CAPTURE_DEVICE_ERR_RET V4l2AllocateBuf(DMA_BUFFER *DevBufQue, unsigned int *pBufQueNum);
virtual CAPTURE_DEVICE_ERR_RET V4l2Prepare();
        virtual CAPTURE_DEVICE_ERR_RET V4l2Start();
        virtual CAPTURE_DEVICE_ERR_RET V4l2Dequeue(unsigned int *pBufQueIdx);
        virtual CAPTURE_DEVICE_ERR_RET V4l2Queue(unsigned int BufQueIdx);
        virtual CAPTURE_DEVICE_ERR_RET V4l2Stop();
        virtual CAPTURE_DEVICE_ERR_RET V4l2DeAlloc();
        virtual CAPTURE_DEVICE_ERR_RET V4l2Close();
        virtual CAPTURE_DEVICE_ERR_RET V4l2ConfigInput(struct capture_config_t *pCapcfg);
        virtual CAPTURE_DEVICE_ERR_RET V4l2GetCaptureMode(struct capture_config_t *pCapcfg, unsigned int *pMode);
        virtual CAPTURE_DEVICE_ERR_RET V4l2SetRot(struct capture_config_t *pCapcfg);

        char         mCaptureDeviceName[CAMAERA_FILENAME_LENGTH];
        char         mInitalDeviceName[CAMAERA_SENSOR_LENGTH];
        int          mCameraDevice;
unsigned int mFmtParamIdx;
        unsigned int mSizeFPSParamIdx;
        unsigned int mRequiredFmt;
        unsigned int mBufQueNum;
        int          mQueuedBufNum;
        DMA_BUFFER mCaptureBuffers[MAX_CAPTURE_BUF_QUE_NUM];
        struct   capture_config_t mCapCfg;

    };
};

2.  经典的调用流程。

具体解析可以看 http://www.linuxidc.com/Linux/2011-03/33022.htm

a. open device  /dev/video16

b . VIDIOC_ENUM_FMT : get video capture supported format

struct v4l2_fmtdesc fmt;

ioctl(dev, VIDIOC_ENUM_FMT, &fmt))

c. VIDIOC_QUERYCAP , get the capture ability

struct v4l2_capability cap; 

iret = ioctl(fd_usbcam, VIDIOC_QUERYCAP, &cap);

d. VIDIOC_S_FMT    , set parameter


   struct v4l2_format tv4l2_format; 

   tv4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

   tv4l2_format.fmt.pix.width = img_width; 

   tv4l2_format.fmt.pix.height = img_height; 

   tv4l2_format.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; 

   tv4l2_format.fmt.pix.field = V4L2_FIELD_INTERLACED; 

   iret = ioctl(fd_usbcam, VIDIOC_S_FMT, &tv4l2_format);

e. VIDIOC_REQBUFS  : get buffer

// Request buffers
struct v4l2_requestbuffers reqbuf;
reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
reqbuf.memory = V4L2_MEMORY_MMAP;
reqbuf.count = BUFFER_COUNT;
ret = ioctl(fd , VIDIOC_REQBUFS, &reqbuf);
if(ret < 0) {
LOG("VIDIOC_REQBUFS failed (%d)\n", ret);
return ret;
}

f. VIDIOC_QUERYBUF

struct v4l2_buffer buf;
for(i=0; i // Query buffer
buf.index = i;
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
ret = ioctl(fd , VIDIOC_QUERYBUF, &buf);
if(ret < 0) {
LOG("VIDIOC_QUERYBUF (%d) failed (%d)\n", i, ret);
return ret;
}

// mmap buffer
framebuf[i].length = buf.length;
framebuf[i].start = (char *) mmap(0, buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, buf.m.offset);
if (framebuf[i].start == MAP_FAILED) {
LOG("mmap (%d) failed: %s\n", i, strerror(errno));
return -1;
}

g. VIDIOC_QBUF

struct v4l2_buffer tV4L2buf; 

memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));

 

tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

tV4L2buf.memory = V4L2_MEMORY_MMAP; 

tV4L2buf.index = i; //(指定)要投放到视频输入队列中的内核空间视频缓冲区的编号;

 

iret = ioctl(fd_usbcam, VIDIOC_QBUF, &tV4L2buf);

H. VIDIOC_STREAMON

enum v4l2_buf_type v4l2type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

fd_set    fds ; 

struct timeval   tv; 

iret = ioctl(fd_usbcam, VIDIOC_STREAMON, &v4l2type);


i. VIDIOC_DQBUF

struct v4l2_buffer tV4L2buf; 

memset(&tV4L2buf, 0, sizeof(struct v4l2_buffer));

 

tV4L2buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

tV4L2buf.memory = V4L2_MEMORY_MMAP; 

 

iret = ioctl(fd_usbcam, VIDIOC_DQBUF, &tV4L2buf);


j. VIDIOC_QBUF  VIDIOC_DQBUF  VIDIOC_QBUF ...... (read data)
k. VIDIOC_STREAMOFF

enum v4l2_buf_type  v4l2type; 

v4l2type = V4L2_BUF_TYPE_VIDEO_CAPTURE;  

iret = ioctl(fd_usbcam, VIDIOC_STREAMOFF, &v4l2type);

3. android 上的实际实现:

与上面的大同小异,贴出两个函数

CAPTURE_DEVICE_ERR_RET V4l2CapDeviceBase :: V4l2Open(){
        CAMERA_HAL_LOG_FUNC;
        int fd = 0, i, j, is_found = 0;
        const char *flags[] = {"uncompressed", "compressed"};

        char   dev_node[CAMAERA_FILENAME_LENGTH];
        DIR *v4l_dir = NULL;
        struct dirent *dir_entry;
        struct v4l2_capability v4l2_cap;
        struct v4l2_fmtdesc vid_fmtdesc;
        struct v4l2_frmsizeenum vid_frmsize;
        CAPTURE_DEVICE_ERR_RET ret = CAPTURE_DEVICE_ERR_NONE;

        if(mCameraDevice > 0)
            return CAPTURE_DEVICE_ERR_ALRADY_OPENED;
        else if (mCaptureDeviceName[0] != '#'){
            CAMERA_HAL_LOG_RUNTIME("already get the device name %s", mCaptureDeviceName);
            mCameraDevice = open(mCaptureDeviceName, O_RDWR, O_NONBLOCK);
            if (mCameraDevice < 0)
                return CAPTURE_DEVICE_ERR_OPEN;
        }
        else{
            CAMERA_HAL_LOG_RUNTIME("deviceName is %s", mInitalDeviceName);
            v4l_dir = opendir("/sys/class/video4linux");
            if (v4l_dir){
                while((dir_entry = readdir(v4l_dir))) {
                    memset((void *)dev_node, 0, CAMAERA_FILENAME_LENGTH);
                    if(strncmp(dir_entry->d_name, "video", 5))
                        continue;
                    sprintf(dev_node, "/dev/%s", dir_entry->d_name);
                    if ((fd = open(dev_node, O_RDWR, O_NONBLOCK)) < 0)
continue;
                    CAMERA_HAL_LOG_RUNTIME("dev_node is %s", dev_node);
                    if(ioctl(fd, VIDIOC_QUERYCAP, &v4l2_cap) < 0 ) {
                        close(fd);
                        continue;
                    } else if ((strstr((char *)v4l2_cap.driver, mInitalDeviceName) != 0) &&
                            (v4l2_cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) {
                        is_found = 1;
                        strcpy(mCaptureDeviceName, dev_node);
                        CAMERA_HAL_LOG_RUNTIME("device name is %s", mCaptureDeviceName);
                        break;
                    } else
                        close(fd);
                }
            }
            if (fd > 0)
                mCameraDevice = fd;
            else{
                CAMERA_HAL_ERR("The device name is not correct or the device is error");
                return CAPTURE_DEVICE_ERR_OPEN;
            }
        }
        return ret;
    }

CAPTURE_DEVICE_ERR_RET V4l2CapDeviceBase :: V4l2AllocateBuf(DMA_BUFFER *DevBufQue, unsigned int *pBufQueNum){
        unsigned int i;
        struct v4l2_buffer buf;
        enum v4l2_buf_type type;
        struct v4l2_requestbuffers req;
        int BufQueNum;

        CAMERA_HAL_LOG_FUNC;
        if (mCameraDevice <= 0 || DevBufQue == NULL || pBufQueNum == NULL || *pBufQueNum == 0){
            return CAPTURE_DEVICE_ERR_BAD_PARAM;
        }

        mBufQueNum = *pBufQueNum;

        memset(&req, 0, sizeof (req));
        req.count = mBufQueNum;
        req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        req.memory = V4L2_MEMORY_MMAP;
        if (ioctl(mCameraDevice, VIDIOC_REQBUFS, &req) < 0) {
            CAMERA_HAL_ERR("v4l_capture_setup: VIDIOC_REQBUFS failed\n");
            return CAPTURE_DEVICE_ERR_SYS_CALL;
        }
 /*the driver may can't meet the request, and return the buf num it can handle*/
        *pBufQueNum = mBufQueNum = req.count;

        for (i = 0; i < mBufQueNum; i++) {
            memset(&buf, 0, sizeof (buf));
            buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            buf.index = i;
            if (ioctl(mCameraDevice, VIDIOC_QUERYBUF, &buf) < 0) {
                CAMERA_HAL_ERR("VIDIOC_QUERYBUF error\n");
                return CAPTURE_DEVICE_ERR_SYS_CALL;
            } else {
                CAMERA_HAL_LOG_RUNTIME("VIDIOC_QUERYBUF ok\n");
            }

            mCaptureBuffers[i].length = DevBufQue[i].length= buf.length;
            mCaptureBuffers[i].phy_offset = DevBufQue[i].phy_offset = (size_t) buf.m.offset;
            mCaptureBuffers[i].virt_start = DevBufQue[i].virt_start = (unsigned char *)mmap (NULL, mCaptureBuffers[i].length,
                    PROT_READ | PROT_WRITE, MAP_SHARED, mCameraDevice, mCaptureBuffers[i].phy_offset);
            memset(mCaptureBuffers[i].virt_start, 0xFF, mCaptureBuffers[i].length);
            CAMERA_HAL_LOG_RUNTIME("capture buffers[%d].length = %d\n", i, mCaptureBuffers[i].length);
            CAMERA_HAL_LOG_RUNTIME("capture buffers[%d].phy_offset = 0x%x\n", i, mCaptureBuffers[i].phy_offset);
            CAMERA_HAL_LOG_RUNTIME("capture buffers[%d].virt_start = 0x%x\n", i, (unsigned int)(mCaptureBuffers[i].virt_start));
        }

        return CAPTURE_DEVICE_ERR_NONE;
    }



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值