• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 The Chromium OS Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 #include "camera_characteristics.h"
8 
9 #include <ctype.h>
10 
11 #include <ios>
12 #include <sstream>
13 
14 #include <base/files/file_util.h>
15 #include <base/logging.h>
16 
17 // /etc/camera/camera_characteristics.conf contains camera information which
18 // driver cannot provide.
19 static const char kCameraCharacteristicsConfigFile[] =
20     "/etc/camera/camera_characteristics.conf";
21 
22 /* Common parameters */
23 static const char kLensFacing[] = "lens_facing";
24 static const char kSensorOrientation[] = "sensor_orientation";
25 static const char kUsbVidPid[] = "usb_vid_pid";
26 static const char kLensInfoAvailableFocalLengths[] =
27     "lens_info_available_focal_lengths";
28 static const char kLensInfoMinimumFocusDistance[] =
29     "lens_info_minimum_focus_distance";
30 static const char kLensInfoOptimalFocusDistance[] =
31     "lens_info_optimal_focus_distance";
32 
33 /* HAL v1 parameters */
34 static const char kHorizontalViewAngle_16_9[] = "horizontal_view_angle_16_9";
35 static const char kHorizontalViewAngle_4_3[] = "horizontal_view_angle_4_3";
36 static const char kVerticalViewAngle_16_9[] = "vertical_view_angle_16_9";
37 static const char kVerticalViewAngle_4_3[] = "vertical_view_angle_4_3";
38 
39 /* HAL v3 parameters */
40 static const char kLensInfoAvailableApertures[] =
41     "lens_info_available_apertures";
42 static const char kSensorInfoPhysicalSize[] = "sensor_info_physical_size";
43 static const char kSensorInfoPixelArraySize[] = "sensor_info_pixel_array_size";
44 
45 /* Special parameters */
46 static const char kFramesToSkipAfterStreamon[] =
47     "frames_to_skip_after_streamon";
48 static const char kResolution1280x960Unsupported[] =
49     "resolution_1280x960_unsupported";
50 static const char kResolution1600x1200Unsupported[] =
51     "resolution_1600x1200_unsupported";
52 static const char kConstantFramerateUnsupported[] =
53     "constant_framerate_unsupported";
54 
55 static const struct DeviceInfo kDefaultCharacteristics = {
56   "",     // device_path
57   "",     // usb_vid
58   "",     // usb_pid
59   0,      // lens_facing
60   0,      // sensor_orientation
61   0,      // frames_to_skip_after_streamon
62   66.5,   // horizontal_view_angle_16_9
63   0.0,    // horizontal_view_angle_4_3
64   {1.6},  // lens_info_available_focal_lengths
65   0.3,    // lens_info_minimum_focus_distance
66   0.5,    // lens_info_optimal_focus_distance
67   42.5,   // vertical_view_angle_16_9
68   0.0,    // vertical_view_angle_4_3
69   false,  // resolution_1280x960_unsupported
70   false,  // resolution_1600x1200_unsupported
71   false,  // constant_framerate_unsupported
72   0,      // sensor_info_pixel_array_size_width
73   0       // sensor_info_pixel_array_size_height
74 };
75 
CameraCharacteristics()76 CameraCharacteristics::CameraCharacteristics() {
77 }
78 
~CameraCharacteristics()79 CameraCharacteristics::~CameraCharacteristics() {
80 }
81 
GetCharacteristicsFromFile(const std::unordered_map<std::string,std::string> & devices)82 const DeviceInfos CameraCharacteristics::GetCharacteristicsFromFile(
83     const std::unordered_map<std::string, std::string>& devices) {
84   const base::FilePath path(kCameraCharacteristicsConfigFile);
85   FILE* file = base::OpenFile(path, "r");
86   if (!file) {
87     LOG(INFO) << __func__ << ": Can't open file "
88               << kCameraCharacteristicsConfigFile;
89     return DeviceInfos();
90   }
91 
92   DeviceInfos tmp_device_infos;
93   char buffer[256], key[256], value[256];
94   uint32_t camera_id;
95   uint32_t module_id = -1;
96   std::string vid, pid;
97   while (fgets(buffer, sizeof(buffer), file)) {
98     // Skip comments and empty lines.
99     if (buffer[0] == '#' || buffer[0] == '\n') {
100       continue;
101     }
102 
103     if (sscanf(buffer, "%[^=]=%s", key, value) != 2) {
104       LOG(ERROR) << __func__ << ": Illegal format: " << buffer;
105       continue;
106     }
107     std::vector<char*> sub_keys;
108     char* sub_key = strtok(key, ".");
109     while (sub_key) {
110       sub_keys.push_back(sub_key);
111       sub_key = strtok(NULL, ".");
112     }
113 
114     if (sscanf(sub_keys[0], "camera%u", &camera_id) != 1) {
115       LOG(ERROR) << __func__ << ": Illegal format: " << sub_keys[0];
116       continue;
117     }
118     if (camera_id > tmp_device_infos.size()) {
119       // Camera id should be ascending by one.
120       LOG(ERROR) << __func__ << ": Invalid camera id: " << camera_id;
121       continue;
122     } else if (camera_id == tmp_device_infos.size()) {
123       tmp_device_infos.push_back(kDefaultCharacteristics);
124     }
125 
126     uint32_t tmp_module_id;
127     // Convert value to lower case.
128     for (char* p = value; *p; ++p) *p = tolower(*p);
129 
130     if (sscanf(sub_keys[1], "module%u", &tmp_module_id) != 1) {
131       AddPerCameraCharacteristic(
132           camera_id, sub_keys[1], value, &tmp_device_infos);
133     } else {
134       if (tmp_module_id != module_id) {
135         vid.clear();
136         pid.clear();
137         module_id = tmp_module_id;
138       }
139       if (strcmp(sub_keys[2], kUsbVidPid) == 0) {
140         char tmp_vid[256], tmp_pid[256];
141         if (sscanf(value, "%[0-9a-z]:%[0-9a-z]", tmp_vid, tmp_pid) != 2) {
142           LOG(ERROR) << __func__ << ": Invalid format: " << sub_keys[2];
143           continue;
144         }
145         vid = tmp_vid;
146         pid = tmp_pid;
147         const auto& device = devices.find(value);
148         if (device != devices.end()) {
149           tmp_device_infos[camera_id].usb_vid = vid;
150           tmp_device_infos[camera_id].usb_pid = pid;
151           tmp_device_infos[camera_id].device_path = device->second;
152         }
153 
154         VLOG(1) << __func__ << ": Camera" << camera_id << " "
155                 << kUsbVidPid << ": " << value;
156       } else if (!vid.empty() && !pid.empty()) {
157         // Some characteristics are module-specific, so only matched ones are
158         // selected.
159         if (tmp_device_infos[camera_id].usb_vid != vid ||
160             tmp_device_infos[camera_id].usb_pid != pid) {
161           VLOG(1) << __func__ << ": Mismatched module: "
162                   << "vid: " << vid << " pid: " << pid;
163           continue;
164         }
165         AddPerModuleCharacteristic(
166             camera_id, sub_keys[2], value, &tmp_device_infos);
167       } else {
168         // Characteristic usb_vid_pid should come before other module-specific
169         // characteristics.
170         LOG(ERROR) << __func__ << ": Illegal format."
171                    << " usb_vid_pid should come before: " << buffer;
172       }
173     }
174   }
175   base::CloseFile(file);
176 
177   DeviceInfos device_infos;
178   // Some devices use the same camera_characteristics.conf and have different
179   // number of cameras.
180   for (size_t id = 0; id < tmp_device_infos.size(); ++id) {
181     if (tmp_device_infos[id].device_path.empty()) {
182       LOG(INFO) << __func__ << ": No matching module for camera" << id;
183     } else {
184       device_infos.push_back(tmp_device_infos[id]);
185     }
186   }
187 
188   // Check sensor array size to decide supported resolutions.
189   for (size_t id = 0; id < device_infos.size(); ++id) {
190     if (device_infos[id].sensor_info_pixel_array_size_width < 1280 ||
191         device_infos[id].sensor_info_pixel_array_size_height < 960) {
192       device_infos[id].resolution_1280x960_unsupported = true;
193     }
194     if (device_infos[id].sensor_info_pixel_array_size_width < 1600 ||
195         device_infos[id].sensor_info_pixel_array_size_height < 1200) {
196       device_infos[id].resolution_1600x1200_unsupported = true;
197     }
198   }
199   return device_infos;
200 }
201 
AddPerCameraCharacteristic(uint32_t camera_id,const char * characteristic,const char * value,DeviceInfos * device_infos)202 void CameraCharacteristics::AddPerCameraCharacteristic(
203     uint32_t camera_id, const char* characteristic, const char* value,
204     DeviceInfos* device_infos) {
205   VLOG(1) << __func__ << ": " << characteristic << ": " << value;
206   if (strcmp(characteristic, kLensFacing) == 0) {
207     (*device_infos)[camera_id].lens_facing = strtol(value, NULL, 10);
208   } else if (strcmp(characteristic, kSensorOrientation) == 0) {
209     (*device_infos)[camera_id].sensor_orientation = strtol(value, NULL, 10);
210   } else {
211     LOG(ERROR) << __func__ << ": Unknown characteristic: " << characteristic
212                << " value: " << value;
213   }
214 }
215 
AddPerModuleCharacteristic(uint32_t camera_id,const char * characteristic,const char * value,DeviceInfos * device_infos)216 void CameraCharacteristics::AddPerModuleCharacteristic(
217     uint32_t camera_id, const char* characteristic, const char* value,
218     DeviceInfos* device_infos) {
219   if (strcmp(characteristic, kFramesToSkipAfterStreamon) == 0) {
220     VLOG(1) << __func__ << ": " << characteristic << ": " << value;
221     (*device_infos)[camera_id].frames_to_skip_after_streamon =
222         strtol(value, NULL, 10);
223   } else if (strcmp(characteristic, kHorizontalViewAngle_16_9) == 0) {
224     AddFloatValue(value, kHorizontalViewAngle_16_9,
225                   &(*device_infos)[camera_id].horizontal_view_angle_16_9);
226   } else if (strcmp(characteristic, kHorizontalViewAngle_4_3) == 0) {
227     AddFloatValue(value, kHorizontalViewAngle_4_3,
228                   &(*device_infos)[camera_id].horizontal_view_angle_4_3);
229   } else if (strcmp(characteristic, kLensInfoAvailableFocalLengths) == 0) {
230     (*device_infos)[camera_id].lens_info_available_focal_lengths.clear();
231     char tmp_value[256];
232     strcpy(tmp_value, value);
233     char* focal_length = strtok(tmp_value, ",");
234     while (focal_length) {
235       float tmp_focal_length = strtof(focal_length, NULL);
236       if (tmp_focal_length != 0.0) {
237         VLOG(1) << __func__ << ": " << characteristic << ": "
238                 << tmp_focal_length;
239         (*device_infos)[camera_id].lens_info_available_focal_lengths.push_back(
240             tmp_focal_length);
241       } else {
242         LOG(ERROR) << __func__ << ": Invalid " << characteristic << ": "
243                    << value;
244         (*device_infos)[camera_id].lens_info_available_focal_lengths.clear();
245         (*device_infos)[camera_id].lens_info_available_focal_lengths.push_back(
246             kDefaultCharacteristics.lens_info_available_focal_lengths[0]);
247         break;
248       }
249       focal_length = strtok(NULL, ",");
250     }
251   } else if (strcmp(characteristic, kLensInfoMinimumFocusDistance) == 0) {
252     AddFloatValue(value, kLensInfoMinimumFocusDistance,
253                   &(*device_infos)[camera_id].lens_info_minimum_focus_distance);
254   } else if (strcmp(characteristic, kLensInfoOptimalFocusDistance) == 0) {
255     AddFloatValue(value, kLensInfoOptimalFocusDistance,
256                   &(*device_infos)[camera_id].lens_info_optimal_focus_distance);
257   } else if (strcmp(characteristic, kVerticalViewAngle_16_9) == 0) {
258     AddFloatValue(value, kVerticalViewAngle_16_9,
259                   &(*device_infos)[camera_id].vertical_view_angle_16_9);
260   } else if (strcmp(characteristic, kVerticalViewAngle_4_3) == 0) {
261     AddFloatValue(value, kVerticalViewAngle_4_3,
262                   &(*device_infos)[camera_id].vertical_view_angle_4_3);
263   } else if (strcmp(characteristic, kLensInfoAvailableApertures) == 0) {
264     /* Do nothing. This is for hal v3 */
265   } else if (strcmp(characteristic, kSensorInfoPhysicalSize) == 0) {
266     /* Do nothing. This is for hal v3 */
267   } else if (strcmp(characteristic, kSensorInfoPixelArraySize) == 0) {
268     int width, height;
269     if (sscanf(value, "%dx%d", &width, &height) != 2) {
270       LOG(ERROR) << __func__ << ": Illegal array size format: " << value;
271       return;
272     }
273     VLOG(1) << __func__ << ": " << characteristic << ": " << width
274             << "x" << height;
275     (*device_infos)[camera_id].sensor_info_pixel_array_size_width = width;
276     (*device_infos)[camera_id].sensor_info_pixel_array_size_height = height;
277   } else if (strcmp(characteristic, kResolution1280x960Unsupported) == 0) {
278     VLOG(1) << __func__ << ": " << characteristic << ": " << value;
279     std::istringstream is(value);
280     is >> std::boolalpha
281        >> (*device_infos)[camera_id].resolution_1280x960_unsupported;
282   } else if (strcmp(characteristic, kResolution1600x1200Unsupported) == 0) {
283     VLOG(1) << __func__ << ": " << characteristic << ": " << value;
284     std::istringstream is(value);
285     is >> std::boolalpha
286        >> (*device_infos)[camera_id].resolution_1600x1200_unsupported;
287   } else if (strcmp(characteristic, kConstantFramerateUnsupported) == 0) {
288     VLOG(1) << __func__ << ": " << characteristic << ": " << value;
289     std::istringstream is(value);
290     is >> std::boolalpha
291        >> (*device_infos)[camera_id].constant_framerate_unsupported;
292   } else {
293     LOG(ERROR) << __func__ << ": Unknown characteristic: " << characteristic
294                << " value: " << value;
295   }
296 }
297 
AddFloatValue(const char * value,const char * characteristic_name,float * characteristic)298 void CameraCharacteristics::AddFloatValue(const char* value,
299                                           const char* characteristic_name,
300                                           float* characteristic) {
301   float tmp_value = strtof(value, NULL);
302   if (tmp_value != 0.0) {
303     VLOG(1) << __func__ << ": " << characteristic_name << ": " << value;
304     *characteristic = tmp_value;
305   } else {
306     LOG(ERROR) << __func__ << ": Invalid " << characteristic_name
307                << ": " << value;
308   }
309 }
310