blob: e466f34dd7754d9bdb96aaba1766b4ee53ac3911 [file] [log] [blame]
Wind Yuan75564b12015-01-15 06:51:15 -05001/*
2 * main.cpp - test
3 *
4 * Copyright (c) 2014 Intel Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Wind Yuan <feng.yuan@intel.com>
19 */
20
21#include "device_manager.h"
22#include "atomisp_device.h"
23#include "isp_controller.h"
24#include "isp_image_processor.h"
25#include "x3a_analyzer_simple.h"
26#if HAVE_IA_AIQ
27#include "x3a_analyzer_aiq.h"
28#endif
Wind Yuand4427312015-02-11 16:09:00 +080029#if HAVE_LIBCL
Wind Yuane4ba0c92015-03-26 16:59:06 +080030#include "cl_3a_image_processor.h"
wangfeicf4c4e72015-05-25 17:11:41 +080031#include "cl_csc_image_processor.h"
Wind Yuane4ba0c92015-03-26 16:59:06 +080032#endif
33#if HAVE_LIBDRM
34#include "drm_display.h"
Wind Yuand4427312015-02-11 16:09:00 +080035#endif
Wind Yuane25ce3f2015-05-04 18:07:29 +080036#include "analyzer_loader.h"
Wind Yuand4427312015-02-11 16:09:00 +080037
Wind Yuan75564b12015-01-15 06:51:15 -050038#include <unistd.h>
39#include <signal.h>
40#include <stdlib.h>
ShincyTue521cf92015-03-27 15:13:51 +080041#include <string>
John Yeae9da732015-01-22 13:36:36 +080042#include "test_common.h"
43
Wind Yuan75564b12015-01-15 06:51:15 -050044using namespace XCam;
45
ShincyTue521cf92015-03-27 15:13:51 +080046static Mutex g_mutex;
47static Cond g_cond;
48static bool g_stop = false;
49
Wind Yuan75564b12015-01-15 06:51:15 -050050class MainDeviceManager
51 : public DeviceManager
52{
53public:
54 MainDeviceManager ()
55 : _file (NULL)
56 , _save_file (false)
57 , _interval (1)
58 , _frame_count (0)
ShincyTue521cf92015-03-27 15:13:51 +080059 , _frame_save (0)
Wind Yuan683f8662015-03-27 18:52:38 +080060 , _enable_display (false)
Wind Yuane4ba0c92015-03-26 16:59:06 +080061 {
62#if HAVE_LIBDRM
63 _display = DrmDisplay::instance();
64#endif
65 }
Wind Yuan75564b12015-01-15 06:51:15 -050066
67 ~MainDeviceManager () {
68 close_file ();
69 }
70
71 void enable_save_file (bool enable) {
72 _save_file = enable;
73 }
74 void set_interval (uint32_t inteval) {
75 _interval = inteval;
76 }
ShincyTue521cf92015-03-27 15:13:51 +080077 void set_frame_save (uint32_t frame_save) {
78 _frame_save = frame_save;
79 }
Wind Yuan75564b12015-01-15 06:51:15 -050080
Wind Yuan683f8662015-03-27 18:52:38 +080081 void enable_display(bool value) {
82 _enable_display = value;
83 }
84
wangfeicf4c4e72015-05-25 17:11:41 +080085 void set_display_mode(DrmDisplayMode mode) {
86 _display->set_display_mode (mode);
87 }
88
Wind Yuan75564b12015-01-15 06:51:15 -050089protected:
90 virtual void handle_message (SmartPtr<XCamMessage> &msg);
91 virtual void handle_buffer (SmartPtr<VideoBuffer> &buf);
92
Wind Yuane4ba0c92015-03-26 16:59:06 +080093 int display_buf (SmartPtr<VideoBuffer> &buf);
94
Wind Yuan75564b12015-01-15 06:51:15 -050095private:
96 void open_file ();
97 void close_file ();
98
99 FILE *_file;
100 bool _save_file;
101 uint32_t _interval;
102 uint32_t _frame_count;
ShincyTue521cf92015-03-27 15:13:51 +0800103 uint32_t _frame_save;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800104 SmartPtr<DrmDisplay> _display;
Wind Yuan683f8662015-03-27 18:52:38 +0800105 bool _enable_display;
Wind Yuan75564b12015-01-15 06:51:15 -0500106};
107
108void
109MainDeviceManager::handle_message (SmartPtr<XCamMessage> &msg)
110{
111 XCAM_UNUSED (msg);
112}
113
114void
115MainDeviceManager::handle_buffer (SmartPtr<VideoBuffer> &buf)
116{
Wind Yuan683f8662015-03-27 18:52:38 +0800117 FPS_CALCULATION (fps_buf, 30);
118
119 if (_enable_display)
120 display_buf (buf);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800121
Wind Yuan75564b12015-01-15 06:51:15 -0500122 if (!_save_file)
123 return ;
124
125 if ((_frame_count++ % _interval) != 0)
126 return;
127
ShincyTue521cf92015-03-27 15:13:51 +0800128 if ((_frame_save != 0) && (_frame_count > _frame_save)) {
129 SmartLock locker (g_mutex);
130 g_stop = true;
131 g_cond.broadcast ();
132 return;
133 }
134
Wind Yuan75564b12015-01-15 06:51:15 -0500135 const VideoBufferInfo & frame_info = buf->get_video_info ();
136 uint8_t *frame = buf->map ();
ShincyTu2808b592015-03-13 17:17:25 +0800137
Wind Yuan75564b12015-01-15 06:51:15 -0500138 if (frame == NULL)
139 return;
ShincyTu2808b592015-03-13 17:17:25 +0800140
141 uint32_t size = 0;
142
143 switch(frame_info.format) {
144 case V4L2_PIX_FMT_NV12: // 420
145 case V4L2_PIX_FMT_NV21:
146 size = XCAM_ALIGN_UP(frame_info.width, 2) * XCAM_ALIGN_UP(frame_info.height, 2) * 3 / 2;
147 break;
148 case V4L2_PIX_FMT_YUV422P: // 422 Planar
149 case V4L2_PIX_FMT_YUYV: // 422
150 case V4L2_PIX_FMT_SBGGR10:
151 case V4L2_PIX_FMT_SGBRG10:
152 case V4L2_PIX_FMT_SGRBG10:
153 case V4L2_PIX_FMT_SRGGB10:
ShincyTu1a4de9d2015-06-01 18:04:51 +0800154 case V4L2_PIX_FMT_SBGGR12:
155 case V4L2_PIX_FMT_SGBRG12:
156 case V4L2_PIX_FMT_SGRBG12:
157 case V4L2_PIX_FMT_SRGGB12:
ShincyTu2808b592015-03-13 17:17:25 +0800158 size = XCAM_ALIGN_UP(frame_info.width, 2) * XCAM_ALIGN_UP(frame_info.height, 2) * 2;
159 break;
160 default:
161 XCAM_LOG_ERROR (
162 "unknown v4l2 format(%s) in buffer handle",
163 xcam_fourcc_to_string (frame_info.format));
164 return;
165 }
166
Wind Yuan75564b12015-01-15 06:51:15 -0500167 open_file ();
168 if (fwrite (frame, size, 1, _file) <= 0) {
169 XCAM_LOG_WARNING ("write frame failed.");
170 }
171}
172
Wind Yuane4ba0c92015-03-26 16:59:06 +0800173int
174MainDeviceManager::display_buf (SmartPtr<VideoBuffer> &buf)
175{
176#if HAVE_LIBDRM
177 XCamReturn ret = XCAM_RETURN_NO_ERROR;
178 const VideoBufferInfo & frame_info = buf->get_video_info ();
179 struct v4l2_rect rect = { 0, 0, (int)frame_info.width, (int)frame_info.height };
180
181 if (!_display->is_render_inited ()) {
wangfei139ea7e2015-04-27 18:13:40 +0800182 ret = _display->render_init (0, 0, 1920, 1080, frame_info.format, &rect);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800183 CHECK (ret, "display failed on render_init");
184 }
185 ret = _display->render_setup_frame_buffer (buf);
186 CHECK (ret, "display failed on framebuf set");
187 ret = _display->render_buffer (buf);
188 CHECK (ret, "display failed on rendering");
189#endif
190 return 0;
191}
192
193
Wind Yuan75564b12015-01-15 06:51:15 -0500194void
195MainDeviceManager::open_file ()
196{
ShincyTue521cf92015-03-27 15:13:51 +0800197 if ((_file) && (_frame_save == 0))
Wind Yuan75564b12015-01-15 06:51:15 -0500198 return;
ShincyTue521cf92015-03-27 15:13:51 +0800199
200 std::string file_name = DEFAULT_SAVE_FILE_NAME;
201
202 if (_frame_save != 0) {
203 file_name += std::to_string(_frame_count);
204 }
205 file_name += ".raw";
206
207 _file = fopen(file_name.c_str(), "wb");
Wind Yuan75564b12015-01-15 06:51:15 -0500208}
209
210void
211MainDeviceManager::close_file ()
212{
213 if (_file)
214 fclose (_file);
215 _file = NULL;
216}
217
218#define V4L2_CAPTURE_MODE_STILL 0x2000
219#define V4L2_CAPTURE_MODE_VIDEO 0x4000
220#define V4L2_CAPTURE_MODE_PREVIEW 0x8000
221
Wind Yuan26e9e212015-04-16 15:55:45 +0800222typedef enum {
223 AnalyzerTypeSimple = 0,
224 AnalyzerTypeAiq,
Wind Yuane25ce3f2015-05-04 18:07:29 +0800225 AnalyzerTypeDynamic,
Wind Yuan26e9e212015-04-16 15:55:45 +0800226} AnalyzerType;
227
Wind Yuan75564b12015-01-15 06:51:15 -0500228void dev_stop_handler(int sig)
229{
230 XCAM_UNUSED (sig);
231
232 SmartLock locker (g_mutex);
233 g_stop = true;
234 g_cond.broadcast ();
235
236 //exit(0);
237}
238
239void print_help (const char *bin_name)
240{
241 printf ("Usage: %s [-a analyzer]\n"
ShincyTue521cf92015-03-27 15:13:51 +0800242 "\t -a analyzer specify a analyzer\n"
Wind Yuane25ce3f2015-05-04 18:07:29 +0800243 "\t select from [simple, aiq, dynamic], default is [simple]\n"
ShincyTue521cf92015-03-27 15:13:51 +0800244 "\t -m mem_type specify video memory type\n"
245 "\t mem_type select from [dma, mmap], default is [mmap]\n"
246 "\t -s save file to %s\n"
247 "\t -n interval save file on every [interval] frame\n"
248 "\t -c process image with cl kernel\n"
249 "\t -f pixel_fmt specify output pixel format\n"
ShincyTu1a4de9d2015-06-01 18:04:51 +0800250 "\t pixel_fmt select from [NV12, YUYV, BA10, RG12], default is [NV12]\n"
ShincyTue521cf92015-03-27 15:13:51 +0800251 "\t -d cap_mode specify capture mode\n"
252 "\t cap_mode select from [video, still], default is [video]\n"
253 "\t -i frame_save specify the frame count to save, default is 0 which means endless\n"
wangfeicf4c4e72015-05-25 17:11:41 +0800254 "\t -p preview on local display\n"
255 "\t -e display_mode preview mode\n"
256 "\t select from [primary, overlay], default is [primary]\n"
ShincyTue521cf92015-03-27 15:13:51 +0800257 "\t -h help\n"
Wind Yuan75564b12015-01-15 06:51:15 -0500258 , bin_name
259 , DEFAULT_SAVE_FILE_NAME);
260}
261
262int main (int argc, char *argv[])
263{
264 XCamReturn ret = XCAM_RETURN_NO_ERROR;
265 SmartPtr<MainDeviceManager> device_manager = new MainDeviceManager;
266 SmartPtr<V4l2Device> device;
267 SmartPtr<V4l2SubDevice> event_device;
268 SmartPtr<IspController> isp_controller;
269 SmartPtr<X3aAnalyzer> analyzer;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800270 SmartPtr<ImageProcessor> isp_processor;
wangfeicf4c4e72015-05-25 17:11:41 +0800271 SmartPtr<CLCscImageProcessor> cl_csc_proccessor;
Wind Yuan26e9e212015-04-16 15:55:45 +0800272 AnalyzerType analyzer_type = AnalyzerTypeSimple;
wangfeicf4c4e72015-05-25 17:11:41 +0800273 DrmDisplayMode display_mode = DRM_DISPLAY_MODE_PRIMARY;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800274#if HAVE_LIBDRM
275 SmartPtr<DrmDisplay> drm_disp = DrmDisplay::instance();
276#endif
277
Wind Yuand4427312015-02-11 16:09:00 +0800278#if HAVE_LIBCL
Wind Yuane4ba0c92015-03-26 16:59:06 +0800279 SmartPtr<CL3aImageProcessor> cl_processor;
Wind Yuand4427312015-02-11 16:09:00 +0800280#endif
281 bool have_cl_processor = false;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800282 bool need_display = false;
Wind Yuand4427312015-02-11 16:09:00 +0800283 enum v4l2_memory v4l2_mem_type = V4L2_MEMORY_MMAP;
Wind Yuan75564b12015-01-15 06:51:15 -0500284 const char *bin_name = argv[0];
285 int opt;
ShincyTu2808b592015-03-13 17:17:25 +0800286 uint32_t capture_mode = V4L2_CAPTURE_MODE_VIDEO;
287 uint32_t pixel_format = V4L2_PIX_FMT_NV12;
Wind Yuan75564b12015-01-15 06:51:15 -0500288
wangfeicf4c4e72015-05-25 17:11:41 +0800289 while ((opt = getopt(argc, argv, "sca:n:m:f:d:pi:e:h")) != -1) {
Wind Yuan75564b12015-01-15 06:51:15 -0500290 switch (opt) {
291 case 'a': {
Wind Yuane25ce3f2015-05-04 18:07:29 +0800292 if (!strcmp (optarg, "dynamic"))
293 analyzer_type = AnalyzerTypeDynamic;
294 else if (!strcmp (optarg, "simple"))
Wind Yuan26e9e212015-04-16 15:55:45 +0800295 analyzer_type = AnalyzerTypeSimple;
Wind Yuan75564b12015-01-15 06:51:15 -0500296#if HAVE_IA_AIQ
297 else if (!strcmp (optarg, "aiq"))
Wind Yuan26e9e212015-04-16 15:55:45 +0800298 analyzer_type = AnalyzerTypeAiq;
Wind Yuan75564b12015-01-15 06:51:15 -0500299#endif
300 else {
301 print_help (bin_name);
302 return -1;
303 }
304 break;
305 }
306
Wind Yuand4427312015-02-11 16:09:00 +0800307 case 'm': {
308 if (!strcmp (optarg, "dma"))
309 v4l2_mem_type = V4L2_MEMORY_DMABUF;
310 else if (!strcmp (optarg, "mmap"))
311 v4l2_mem_type = V4L2_MEMORY_MMAP;
312 else
313 print_help (bin_name);
314 break;
315 }
316
Wind Yuan75564b12015-01-15 06:51:15 -0500317 case 's':
318 device_manager->enable_save_file (true);
319 break;
320 case 'n':
321 device_manager->set_interval (atoi(optarg));
322 break;
Wind Yuand4427312015-02-11 16:09:00 +0800323 case 'c':
324 have_cl_processor = true;
325 break;
ShincyTu2808b592015-03-13 17:17:25 +0800326 case 'f':
ShincyTuc8466402015-03-31 11:03:39 +0800327 CHECK_EXP ((strlen(optarg) == 4), "invalid pixel format\n");
328 pixel_format = v4l2_fourcc ((unsigned)optarg[0],
329 (unsigned)optarg[1],
330 (unsigned)optarg[2],
331 (unsigned)optarg[3]);
ShincyTu2808b592015-03-13 17:17:25 +0800332 break;
333 case 'd':
334 if (!strcmp (optarg, "still"))
335 capture_mode = V4L2_CAPTURE_MODE_STILL;
336 else if (!strcmp (optarg, "video"))
337 capture_mode = V4L2_CAPTURE_MODE_VIDEO;
338 else {
339 print_help (bin_name);
340 return -1;
341 }
342 break;
Wind Yuane4ba0c92015-03-26 16:59:06 +0800343 case 'p':
344 need_display = true;
345 break;
wangfeicf4c4e72015-05-25 17:11:41 +0800346 case 'e': {
347 if (!strcmp (optarg, "primary"))
348 display_mode = DRM_DISPLAY_MODE_PRIMARY;
349 else if (!strcmp (optarg, "overlay"))
350 display_mode = DRM_DISPLAY_MODE_OVERLAY;
351 else {
352 print_help (bin_name);
353 return -1;
354 }
355 break;
356 }
ShincyTue521cf92015-03-27 15:13:51 +0800357 case 'i':
358 device_manager->set_frame_save(atoi(optarg));
359 break;
Wind Yuan75564b12015-01-15 06:51:15 -0500360 case 'h':
361 print_help (bin_name);
362 return 0;
363
364 default:
365 print_help (bin_name);
366 return -1;
367 }
368 }
369
wangfeicf4c4e72015-05-25 17:11:41 +0800370 if (need_display) {
Wind Yuan683f8662015-03-27 18:52:38 +0800371 device_manager->enable_display (true);
wangfeicf4c4e72015-05-25 17:11:41 +0800372 device_manager->set_display_mode (display_mode);
373 }
ShincyTu2808b592015-03-13 17:17:25 +0800374 if (!device.ptr ()) {
375 if (capture_mode == V4L2_CAPTURE_MODE_STILL)
376 device = new AtomispDevice (CAPTURE_DEVICE_STILL);
377 else if (capture_mode == V4L2_CAPTURE_MODE_VIDEO)
378 device = new AtomispDevice (CAPTURE_DEVICE_VIDEO);
379 else
380 device = new AtomispDevice (DEFAULT_CAPTURE_DEVICE);
381 }
Wind Yuan75564b12015-01-15 06:51:15 -0500382 if (!event_device.ptr ())
383 event_device = new V4l2SubDevice (DEFAULT_EVENT_DEVICE);
384 if (!isp_controller.ptr ())
385 isp_controller = new IspController (device);
Wind Yuan26e9e212015-04-16 15:55:45 +0800386
387 switch (analyzer_type) {
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800388 case AnalyzerTypeSimple:
389 analyzer = new X3aAnalyzerSimple ();
390 break;
Wind Yuan26e9e212015-04-16 15:55:45 +0800391#if HAVE_IA_AIQ
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800392 case AnalyzerTypeAiq:
393 analyzer = new X3aAnalyzerAiq (isp_controller, DEFAULT_CPF_FILE);
394 break;
Wind Yuan26e9e212015-04-16 15:55:45 +0800395#endif
Wind Yuane25ce3f2015-05-04 18:07:29 +0800396 case AnalyzerTypeDynamic: {
397 const char *path_of_3a = DEFAULT_DYNAMIC_3A_LIB;
398 SmartPtr<AnalyzerLoader> loader = new AnalyzerLoader (path_of_3a);
399 analyzer = loader->load_analyzer (loader);
400 CHECK_EXP (analyzer.ptr (), "load dynamic 3a lib(%s) failed", path_of_3a);
401 break;
402 }
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800403 default:
404 print_help (bin_name);
405 return -1;
Wind Yuan26e9e212015-04-16 15:55:45 +0800406 }
Wind Yuan75564b12015-01-15 06:51:15 -0500407
408 signal(SIGINT, dev_stop_handler);
409
410 device->set_sensor_id (0);
ShincyTu2808b592015-03-13 17:17:25 +0800411 device->set_capture_mode (capture_mode);
Wind Yuan75564b12015-01-15 06:51:15 -0500412 //device->set_mem_type (V4L2_MEMORY_DMABUF);
Wind Yuand4427312015-02-11 16:09:00 +0800413 device->set_mem_type (v4l2_mem_type);
Wind Yuan75564b12015-01-15 06:51:15 -0500414 device->set_buffer_count (8);
ShincyTu1a4de9d2015-06-01 18:04:51 +0800415 if (pixel_format == V4L2_PIX_FMT_SRGGB12)
416 device->set_framerate (30, 1);
417 else
418 device->set_framerate (25, 1);
Wind Yuan75564b12015-01-15 06:51:15 -0500419 ret = device->open ();
420 CHECK (ret, "device(%s) open failed", device->get_device_name());
ShincyTu2808b592015-03-13 17:17:25 +0800421 ret = device->set_format (1920, 1080, pixel_format, V4L2_FIELD_NONE, 1920 * 2);
Wind Yuan75564b12015-01-15 06:51:15 -0500422 CHECK (ret, "device(%s) set format failed", device->get_device_name());
423
424 ret = event_device->open ();
425 CHECK (ret, "event device(%s) open failed", event_device->get_device_name());
426 int event = V4L2_EVENT_ATOMISP_3A_STATS_READY;
427 ret = event_device->subscribe_event (event);
428 CHECK_CONTINUE (
429 ret,
430 "device(%s) subscribe event(%d) failed",
431 event_device->get_device_name(), event);
432 event = V4L2_EVENT_FRAME_SYNC;
433 ret = event_device->subscribe_event (event);
434 CHECK_CONTINUE (
435 ret,
436 "device(%s) subscribe event(%d) failed",
437 event_device->get_device_name(), event);
438
439 device_manager->set_capture_device (device);
440 device_manager->set_event_device (event_device);
441 device_manager->set_isp_controller (isp_controller);
442 if (analyzer.ptr())
443 device_manager->set_analyzer (analyzer);
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800444
445 if (have_cl_processor)
446 isp_processor = new IspExposureImageProcessor (isp_controller);
447 else
448 isp_processor = new IspImageProcessor (isp_controller);
449
450 XCAM_ASSERT (isp_processor.ptr ());
Wind Yuane4ba0c92015-03-26 16:59:06 +0800451 device_manager->add_image_processor (isp_processor);
wangfeicf4c4e72015-05-25 17:11:41 +0800452 if ((display_mode == DRM_DISPLAY_MODE_PRIMARY) && need_display && (!have_cl_processor)) {
453 cl_csc_proccessor = new CLCscImageProcessor();
454 XCAM_ASSERT (cl_csc_proccessor.ptr ());
455 device_manager->add_image_processor (cl_csc_proccessor);
456 }
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800457
Wind Yuand4427312015-02-11 16:09:00 +0800458#if HAVE_LIBCL
459 if (have_cl_processor) {
Wind Yuane4ba0c92015-03-26 16:59:06 +0800460 cl_processor = new CL3aImageProcessor ();
Wind Yuan7ddf2602015-04-14 18:49:45 +0800461 cl_processor->set_stats_callback(device_manager);
Wind Yuan3d1d15e2015-04-16 17:40:47 +0800462 //cl_processor->set_hdr (true);
Juan Zhaoab5e6fe2015-04-08 14:12:46 +0800463 cl_processor->set_denoise (false);
Wind Yuane4ba0c92015-03-26 16:59:06 +0800464 if (need_display) {
465 cl_processor->set_output_format (V4L2_PIX_FMT_XBGR32);
466 }
ShincyTueace4f22015-04-29 17:40:36 +0800467 cl_processor->set_snr (false);
Wind Yuand4427312015-02-11 16:09:00 +0800468 device_manager->add_image_processor (cl_processor);
469 }
470#endif
Wind Yuane4ba0c92015-03-26 16:59:06 +0800471
Wind Yuan75564b12015-01-15 06:51:15 -0500472 ret = device_manager->start ();
473 CHECK (ret, "device manager start failed");
474
475 // wait for interruption
476 {
477 SmartLock locker (g_mutex);
478 while (!g_stop)
479 g_cond.wait (g_mutex);
480 }
481
482 ret = device_manager->stop();
483 CHECK_CONTINUE (ret, "device manager stop failed");
484 device->close ();
485 event_device->close ();
486
487 return 0;
488}