mx53 camera s5k5bbgx驱动分析

news/2024/10/17 22:19:45/


一: 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);elsegpio_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;} elseclose(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;}




http://www.ppmy.cn/news/349511.html

相关文章

Office 2010安装时缺少MSXML 6.10.1129.0

一、下载MSXML6组件 官方下载 二、安装组件 根据电脑系统位数&#xff08;32位即x86、64位即x64&#xff09;&#xff0c;安装对应的MSXML6组件。 三、注册组件 用WINR组合键调出运行&#xff08;或&#xff1a;左下角“开始”菜单→运行…&#xff09;注意先后顺序 第一次…

安装MS office2010 提示安装msxml6.0.....

问题描述 安装Office2010时&#xff0c;提示需要在计算机上安装MSXML版本6.10.1129.0 解决方法 下载msxml6安装文件http://download.csdn.net/detail/gnail_oug/9501320 &#xff0c;内含32位和64位也可以直接在微软下载中心下载msxml6&#xff0c;下载地址 安装好之后&#…

《Office 365 开发入门指南》

终于等来了这一天&#xff0c;可以为我的这本新书画上一个句号。我记得是在今年的2月份从西雅图回来之后&#xff0c;就萌发了要为中国的Office 365开发人员写一些东西并最终能帮到更多中国用户的想法&#xff0c;而从2月26日正式写下了第一篇&#xff0c;到今天正好是整整十个…

Dynamics365业务(二)

导航至 Dynamics 365 Customer Engagement 应用并在其中导航 用户可以通过多种方式访问 Dynamics 365 应用程序&#xff0c;具体取决于他们的需要和他们正在使用的设备类型。某些应用程序&#xff08;例如 Dynamics 365 Field Service 和 Dynamics 365 Sales&#xff09;具有专…

【离散数学】特殊关系

目录 概述 相容关系 集合的覆盖 等价关系的定义 集合的划分 等价类和商集 等价关系与划分 次序关系 全序关系 函数 函数的运算 特殊关系的应用 概述 关系是数学中一个重要的概念&#xff0c;不同类型的关系在各自的领域中都有着广泛的应用。本篇博客将会介绍相容关…

Office 365 2021密钥版 m1芯片支持

Office 365最新版本包含经典组件Word、Excel、PowerPoint、Outlook和 OneNote&#xff0c;包括了过去在Office 365中添加的一些增强功能&#xff0c;并且支持功能升级和版本升级&#xff01;&#xff01;在新版Office 365中有许多新功能改进&#xff1a;包括PowerPoint的变形和…

Microsoft Office for Mac 2021 (Office 365) 16.55 Universal

请访问原文链接&#xff1a;https://sysin.org/blog/office-2021-for-mac/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者&#xff1a;gc(at)sysin.org&#xff0c;主页&#xff1a;www.sysin.org 2021.09.16&#xff0c;微软正式发布了 Office LTSC 20…

【大学计算机技术】第一章 测试18

文章目录 选择题 选择题 鼠标器通常有两个按键&#xff0c;按键的动作会以电信号形式传送给主机&#xff0c;按键操作的作用主要由( ) 决定。 A. CPU类型 B. 正在运行的软件 C. 鼠标器的接口 D. 鼠标器硬件本身 正确答案&#xff1a; B 关于鼠标器&#xff0c;下面叙述错误的是…