stream pushing ok without access permission of /dev/video0
[rtmpclient.git] / app / src / main / jni / libuvc-0.0.6 / src / ctrl-gen.py
1 #!/usr/bin/env python
2 from __future__ import print_function
3 from collections import OrderedDict
4 import getopt
5 import sys
6 import yaml
7
8 class quoted(str): pass
9
10 def quoted_presenter(dumper, data):
11     return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='"')
12 yaml.add_representer(quoted, quoted_presenter)
13
14 class literal(str): pass
15
16 def literal_presenter(dumper, data):
17     return dumper.represent_scalar('tag:yaml.org,2002:str', data, style='|')
18 yaml.add_representer(literal, literal_presenter)
19
20 def ordered_dict_presenter(dumper, data):
21     return dumper.represent_dict(data.items())
22 yaml.add_representer(OrderedDict, ordered_dict_presenter)
23
24 def dict_constructor(loader, node):
25     return OrderedDict(loader.construct_pairs(node))
26 _mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG
27 yaml.add_constructor(_mapping_tag, dict_constructor)
28
29 class IntField(object):
30     def __init__(self, name, position, length, signed):
31         self.name = name
32         self.position = position
33         self.length = length
34         self.signed = signed
35
36         if not self.length in [1, 2, 4]:
37             raise Exception("bad length " + str(self.length))
38
39         self.user_type = ('u' if not signed else '') + 'int' + str(length * 8) + '_t'
40
41     def getter_sig(self):
42         return "{0}* {1}".format(self.user_type, self.name)
43
44     def unpack(self):
45         if self.length == 1:
46             return "*{0} = data[{1}];".format(self.name, self.position)
47         elif self.length == 2:
48             return "*{0} = SW_TO_SHORT(data + {1});".format(self.name, self.position)
49         elif self.length == 4:
50             return "*{0} = DW_TO_INT(data + {1});".format(self.name, self.position)
51
52     def setter_sig(self):
53         return "{0} {1}".format(self.user_type, self.name)
54
55     def pack(self):
56         if self.length == 1:
57             return "data[{0}] = {1};".format(self.position, self.name)
58         elif self.length == 2:
59             return "SHORT_TO_SW({0}, data + {1});".format(self.name, self.position)
60         elif self.length == 4:
61             return "INT_TO_DW({0}, data + {1});".format(self.name, self.position)
62
63     def spec(self):
64         rep = [('position', self.position), ('length', self.length)]
65         if self.signed:
66             rep.append(('signed', True))
67         return rep
68
69     @staticmethod
70     def load(spec):
71         return IntField(spec['name'], spec['position'], spec['length'], spec['signed'] if signed in spec else False)
72
73 def load_field(name, spec):
74     if spec['type'] == 'int':
75         return IntField(name, spec['position'], spec['length'], spec.get('signed', False))
76     else:
77         raise Exception("unknown field type '{0}'".format(spec['type']))
78
79 GETTER_TEMPLATE = """/** @ingroup ctrl
80  * {gen_doc}
81  * @param devh UVC device handle
82  * {args_doc}
83  * @param req_code UVC_GET_* request to execute
84  */
85 uvc_error_t uvc_get_{control_name}(uvc_device_handle_t *devh, {args_signature}, enum uvc_req_code req_code) {{
86   uint8_t data[{control_length}];
87   uvc_error_t ret;
88
89   ret = libusb_control_transfer(
90     devh->usb_devh,
91     REQ_TYPE_GET, req_code,
92     {control_code} << 8,
93     {unit_fn} << 8 | devh->info->ctrl_if.bInterfaceNumber,
94     data,
95     sizeof(data),
96     0);
97
98   if (ret == sizeof(data)) {{
99     {unpack}
100     return UVC_SUCCESS;
101   }} else {{
102     return ret;
103   }}
104 }}
105 """
106
107 SETTER_TEMPLATE = """/** @ingroup ctrl
108  * {gen_doc}
109  * @param devh UVC device handle
110  * {args_doc}
111  */
112 uvc_error_t uvc_set_{control_name}(uvc_device_handle_t *devh, {args_signature}) {{
113   uint8_t data[{control_length}];
114   uvc_error_t ret;
115
116   {pack}
117
118   ret = libusb_control_transfer(
119     devh->usb_devh,
120     REQ_TYPE_SET, UVC_SET_CUR,
121     {control_code} << 8,
122     {unit_fn} << 8 | devh->info->ctrl_if.bInterfaceNumber,
123     data,
124     sizeof(data),
125     0);
126
127   if (ret == sizeof(data))
128     return UVC_SUCCESS;
129   else
130     return ret;
131 }}
132 """
133
134 def gen_decl(unit_name, unit, control_name, control):
135     fields = [(load_field(field_name, field_details), field_details['doc']) for field_name, field_details in control['fields'].items()] if 'fields' in control else []
136
137     get_args_signature = ', '.join([field.getter_sig() for (field, desc) in fields])
138     set_args_signature = ', '.join([field.setter_sig() for (field, desc) in fields])
139
140     return "uvc_error_t uvc_get_{function_name}(uvc_device_handle_t *devh, {args_signature}, enum uvc_req_code req_code);\n".format(**{
141         "function_name": control_name,
142         "args_signature": get_args_signature
143     }) + "uvc_error_t uvc_set_{function_name}(uvc_device_handle_t *devh, {args_signature});\n".format(**{
144         "function_name": control_name,
145         "args_signature": set_args_signature
146     })
147
148 def gen_ctrl(unit_name, unit, control_name, control):
149     fields = [(load_field(field_name, field_details), field_details['doc']) for field_name, field_details in control['fields'].items()] if 'fields' in control else []
150
151     get_args_signature = ', '.join([field.getter_sig() for (field, desc) in fields])
152     set_args_signature = ', '.join([field.setter_sig() for (field, desc) in fields])
153     unpack = "\n    ".join([field.unpack() for (field, desc) in fields])
154     pack = "\n  ".join([field.pack() for (field, desc) in fields])
155
156     get_gen_doc_raw = None
157     set_gen_doc_raw = None
158
159     if 'doc' in control:
160         doc = control['doc']
161
162         if isinstance(doc, str):
163             get_gen_doc_raw = "\n * ".join(doc.splitlines())
164             set_gen_doc_raw = get_gen_doc_raw
165         else:
166             if 'get' in doc:
167                 get_gen_doc_raw = "\n * ".join(doc['get'].splitlines())
168             if 'set' in doc:
169                 set_gen_doc_raw = "\n * ".join(doc['set'].splitlines())
170
171     if get_gen_doc_raw is not None:
172         get_gen_doc = get_gen_doc_raw.format(gets_sets='Reads')
173     else:
174         get_gen_doc = '@brief Reads the ' + control['control'] + ' control.'
175
176     if set_gen_doc_raw is not None:
177         set_gen_doc = set_gen_doc_raw.format(gets_sets='Sets')
178     else:
179         set_gen_doc = '@brief Sets the ' + control['control'] + ' control.'
180
181     get_args_doc = "\n * ".join(["@param[out] {0} {1}".format(field.name, desc) for (field, desc) in fields])
182     set_args_doc = "\n * ".join(["@param {0} {1}".format(field.name, desc) for (field, desc) in fields])
183
184     control_code = 'UVC_' + unit['control_prefix'] + '_' + control['control'] + '_CONTROL'
185
186     unit_fn = "uvc_get_camera_terminal(devh)->bTerminalID" if (unit_name == "camera_terminal") else ("uvc_get_" + unit_name + "s(devh)->bUnitID")
187
188     return GETTER_TEMPLATE.format(
189         unit=unit,
190         unit_fn=unit_fn,
191         control_name=control_name,
192         control_code=control_code,
193         control_length=control['length'],
194         args_signature=get_args_signature,
195         args_doc=get_args_doc,
196         gen_doc=get_gen_doc,
197         unpack=unpack) + "\n\n" + SETTER_TEMPLATE.format(
198             unit=unit,
199             unit_fn=unit_fn,
200             control_name=control_name,
201             control_code=control_code,
202             control_length=control['length'],
203             args_signature=set_args_signature,
204             args_doc=set_args_doc,
205             gen_doc=set_gen_doc,
206             pack=pack
207         )
208
209 def export_unit(unit):
210     def fmt_doc(doc):
211         def wrap_doc_entry(entry):
212             if "\n" in entry:
213                 return literal(entry)
214             else:
215                 return entry
216
217         if isinstance(doc, str):
218             return wrap_doc_entry(doc)
219         else:
220             return OrderedDict([(mode, wrap_doc_entry(text)) for mode, text in doc.items()])
221
222     def fmt_ctrl(control_name, control_details):
223         contents = OrderedDict()
224         contents['control'] = control_details['control']
225         contents['length'] = control_details['length']
226         contents['fields'] = control_details['fields']
227
228         if 'doc' in control_details:
229             contents['doc'] = fmt_doc(control_details['doc'])
230
231         return (control_name, contents)
232
233     unit_out = OrderedDict()
234     unit_out['type'] = unit['type']
235     if 'guid' in unit:
236         unit_out['guid'] = unit['guid']
237     if 'description' in unit:
238         unit_out['description'] = unit['description']
239     if 'control_prefix' in unit:
240         unit_out['control_prefix'] = unit['control_prefix']
241     unit_out['controls'] = OrderedDict([fmt_ctrl(ctrl_name, ctrl_details) for ctrl_name, ctrl_details in unit['controls'].items()])
242     return unit_out
243
244 if __name__ == '__main__':
245     try:
246         opts, args = getopt.getopt(sys.argv[1:], "hi:", ["help", "input="])
247     except getopt.GetoptError as err:
248         print(str(err))
249         usage()
250         sys.exit(-1)
251
252     inputs = []
253
254     for opt, val in opts:
255         if opt in ('-h', '--help'):
256             usage()
257             sys.exit(0)
258         elif opt in ('-i', '--input'):
259             inputs.append(val)
260
261     mode = None
262     for arg in args:
263         if arg in ('def', 'decl', 'yaml'):
264             if mode is None:
265                 mode = arg
266             else:
267                 print("Can't specify more than one mode")
268                 sys.exit(-1)
269         else:
270             print("Invalid mode '{0}'".format(arg))
271             sys.exit(-1)
272
273     def iterunits():
274         for input_file in inputs:
275             with open(input_file, "r") as fp:
276                 units = yaml.load(fp)['units']
277                 for unit_name, unit_details in units.iteritems():
278                     yield unit_name, unit_details
279
280     if mode == 'def':
281         print("""/* This is an AUTO-GENERATED file! Update it with the output of `ctrl-gen.py def`. */
282 #include "libuvc/libuvc.h"
283 #include "libuvc/libuvc_internal.h"
284
285 static const int REQ_TYPE_SET = 0x21;
286 static const int REQ_TYPE_GET = 0xa1;
287 """)
288         fun = gen_ctrl
289     elif mode == 'decl':
290         fun = gen_decl
291     elif mode == 'yaml':
292         exported_units = OrderedDict()
293         for unit_name, unit_details in iterunits():
294             exported_units[unit_name] = export_unit(unit_details)
295
296         yaml.dump({'units': exported_units}, sys.stdout, default_flow_style=False)
297         sys.exit(0)
298
299     for unit_name, unit_details in iterunits():
300         for control_name, control_details in unit_details['controls'].iteritems():
301             code = fun(unit_name, unit_details, control_name, control_details)
302             print(code)