10
10
#include <linux/list.h>
11
11
#include <linux/module.h>
12
12
#include <linux/usb.h>
13
+ #include <linux/usb/uvc.h>
13
14
#include <linux/videodev2.h>
14
15
15
16
#include <media/v4l2-ioctl.h>
@@ -166,6 +167,71 @@ static const struct v4l2_file_operations uvc_meta_fops = {
166
167
.mmap = vb2_fop_mmap ,
167
168
};
168
169
170
+ static struct uvc_entity * uvc_meta_find_msxu (struct uvc_device * dev )
171
+ {
172
+ static const u8 uvc_msxu_guid [16 ] = UVC_GUID_MSXU_1_5 ;
173
+ struct uvc_entity * entity ;
174
+
175
+ list_for_each_entry (entity , & dev -> entities , list ) {
176
+ if (!memcmp (entity -> guid , uvc_msxu_guid , sizeof (entity -> guid )))
177
+ return entity ;
178
+ }
179
+
180
+ return NULL ;
181
+ }
182
+
183
+ #define MSXU_CONTROL_METADATA 0x9
184
+ static int uvc_meta_detect_msxu (struct uvc_device * dev )
185
+ {
186
+ u32 * data __free (kfree ) = NULL ;
187
+ struct uvc_entity * entity ;
188
+ int ret ;
189
+
190
+ entity = uvc_meta_find_msxu (dev );
191
+ if (!entity )
192
+ return 0 ;
193
+
194
+ /*
195
+ * USB requires buffers aligned in a special way, simplest way is to
196
+ * make sure that query_ctrl will work is to kmalloc() them.
197
+ */
198
+ data = kmalloc (sizeof (* data ), GFP_KERNEL );
199
+ if (!data )
200
+ return - ENOMEM ;
201
+
202
+ /* Check if the metadata is already enabled. */
203
+ ret = uvc_query_ctrl (dev , UVC_GET_CUR , entity -> id , dev -> intfnum ,
204
+ MSXU_CONTROL_METADATA , data , sizeof (* data ));
205
+ if (ret )
206
+ return 0 ;
207
+
208
+ if (* data ) {
209
+ dev -> quirks |= UVC_QUIRK_MSXU_META ;
210
+ return 0 ;
211
+ }
212
+
213
+ /*
214
+ * We have seen devices that require 1 to enable the metadata, others
215
+ * requiring a value != 1 and others requiring a value >1. Luckily for
216
+ * us, the value from GET_MAX seems to work all the time.
217
+ */
218
+ ret = uvc_query_ctrl (dev , UVC_GET_MAX , entity -> id , dev -> intfnum ,
219
+ MSXU_CONTROL_METADATA , data , sizeof (* data ));
220
+ if (ret || !* data )
221
+ return 0 ;
222
+
223
+ /*
224
+ * If we can set MSXU_CONTROL_METADATA, the device will report
225
+ * metadata.
226
+ */
227
+ ret = uvc_query_ctrl (dev , UVC_SET_CUR , entity -> id , dev -> intfnum ,
228
+ MSXU_CONTROL_METADATA , data , sizeof (* data ));
229
+ if (!ret )
230
+ dev -> quirks |= UVC_QUIRK_MSXU_META ;
231
+
232
+ return 0 ;
233
+ }
234
+
169
235
int uvc_meta_register (struct uvc_streaming * stream )
170
236
{
171
237
struct uvc_device * dev = stream -> dev ;
@@ -179,9 +245,14 @@ int uvc_meta_register(struct uvc_streaming *stream)
179
245
& uvc_meta_fops , & uvc_meta_ioctl_ops );
180
246
}
181
247
182
- void uvc_meta_init (struct uvc_device * dev )
248
+ int uvc_meta_init (struct uvc_device * dev )
183
249
{
184
250
unsigned int i = 0 ;
251
+ int ret ;
252
+
253
+ ret = uvc_meta_detect_msxu (dev );
254
+ if (ret )
255
+ return ret ;
185
256
186
257
dev -> meta_formats [i ++ ] = V4L2_META_FMT_UVC ;
187
258
@@ -195,4 +266,6 @@ void uvc_meta_init(struct uvc_device *dev)
195
266
196
267
/* IMPORTANT: for new meta-formats update UVC_MAX_META_DATA_FORMATS. */
197
268
dev -> meta_formats [i ++ ] = 0 ;
269
+
270
+ return 0 ;
198
271
}
0 commit comments