您的位置:首页 > Web前端

mx53 camera s5k5bbgx驱动分析

2012-04-06 13:17 274 查看
一: linux驱动层

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

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

/*

声明s5k5bbgx的IIC 资源

*/

[cpp] view
plaincopy

<span style="font-size:16px;">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,

},

}

</span>

[cpp] view
plaincopy

<span style="font-size:16px;">/*!

* 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));

}</span>

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

/*

* 注册IIC驱动

*/

[cpp] view
plaincopy

<span style="font-size:16px;">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;

}

<strong>

</strong></span>

至此IIC注册完毕

b: 注册 v4l2 slave device:

[cpp] view
plaincopy

<span style="font-size:16px;">/*!

* 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);

}

</span>

v4l2 slave device 注册完毕

c: s5k5bbgx 初始化和操作

[cpp] view
plaincopy

<span style="font-size:16px;">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;

}

}

</span>

二,V4L2 capture应用

1.接口

[cpp] view
plaincopy

<span style="font-size:16px;">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;

};

};

</span>

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 上的实际实现:

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

[cpp] view
plaincopy

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;

}

[cpp] view
plaincopy

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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息