11
11
#include <zephyr/drivers/display.h>
12
12
#include <zephyr/drivers/video.h>
13
13
#include <zephyr/drivers/video-controls.h>
14
-
14
+ #include <zephyr/usb/usbh.h>
15
15
#include <zephyr/logging/log.h>
16
16
17
17
#ifdef CONFIG_TEST
@@ -22,9 +22,8 @@ LOG_MODULE_REGISTER(main, LOG_LEVEL_DBG);
22
22
LOG_MODULE_REGISTER (main , CONFIG_LOG_DEFAULT_LEVEL );
23
23
#endif
24
24
25
- #if !DT_HAS_CHOSEN (zephyr_camera )
26
- #error No camera chosen in devicetree. Missing "--shield" or "--snippet video-sw-generator" flag?
27
- #endif
25
+ USBH_CONTROLLER_DEFINE (uhs_ctx , DEVICE_DT_GET (DT_NODELABEL (zephyr_uhc0 )));
26
+ const struct device * const uvc_host = DEVICE_DT_GET (DT_NODELABEL (uvc_host ));
28
27
29
28
#if DT_HAS_CHOSEN (zephyr_display )
30
29
static inline int display_setup (const struct device * const display_dev , const uint32_t pixfmt )
@@ -75,8 +74,8 @@ static inline int display_setup(const struct device *const display_dev, const ui
75
74
}
76
75
77
76
static inline void video_display_frame (const struct device * const display_dev ,
78
- const struct video_buffer * const vbuf ,
79
- const struct video_format fmt )
77
+ const struct video_buffer * const vbuf ,
78
+ const struct video_format fmt )
80
79
{
81
80
struct display_buffer_descriptor buf_desc = {
82
81
.buf_size = vbuf -> bytesused ,
@@ -89,15 +88,22 @@ static inline void video_display_frame(const struct device *const display_dev,
89
88
}
90
89
#endif
91
90
91
+ /* TODO: handle disconnection,etc.. */
92
+ static void video_uvc_device_signal_handler (void )
93
+ {
94
+ }
95
+
92
96
int main (void )
93
97
{
94
98
struct video_buffer * buffers [CONFIG_VIDEO_BUFFER_POOL_NUM_MAX ];
95
99
struct video_buffer * vbuf = & (struct video_buffer ){};
96
- const struct device * video_dev ;
97
100
struct video_format fmt ;
98
101
struct video_caps caps ;
99
102
struct video_frmival frmival ;
100
103
struct video_frmival_enum fie ;
104
+ struct k_poll_signal sig ;
105
+ struct k_poll_event evt [1 ];
106
+ k_timeout_t timeout = K_FOREVER ;
101
107
enum video_buf_type type = VIDEO_BUF_TYPE_OUTPUT ;
102
108
#if (CONFIG_VIDEO_SOURCE_CROP_WIDTH && CONFIG_VIDEO_SOURCE_CROP_HEIGHT ) || \
103
109
CONFIG_VIDEO_FRAME_HEIGHT || CONFIG_VIDEO_FRAME_WIDTH
@@ -116,17 +122,58 @@ int main(void)
116
122
return 0 ;
117
123
}
118
124
119
- video_dev = DEVICE_DT_GET (DT_CHOSEN (zephyr_camera ));
120
- if (!device_is_ready (video_dev )) {
121
- LOG_ERR ("%s: video device is not ready" , video_dev -> name );
125
+ if (!device_is_ready (uvc_host )) {
126
+ LOG_ERR ("%s: USB host is not ready" , uvc_host -> name );
122
127
return 0 ;
123
128
}
129
+ LOG_INF ("USB host: %s" , uvc_host -> name );
124
130
125
- LOG_INF ("Video device: %s" , video_dev -> name );
131
+ err = usbh_init (& uhs_ctx );
132
+ if (err ) {
133
+ LOG_ERR ("Failed to initialize host support" );
134
+ return err ;
135
+ }
136
+
137
+ err = usbh_enable (& uhs_ctx );
138
+ if (err ) {
139
+ LOG_ERR ("Failed to enable USB host support" );
140
+ return err ;
141
+ }
142
+
143
+ k_poll_signal_init (& sig );
144
+ k_poll_event_init (& evt [0 ], K_POLL_TYPE_SIGNAL , K_POLL_MODE_NOTIFY_ONLY , & sig );
145
+
146
+ err = video_set_signal (uvc_host , & sig );
147
+ if (err != 0 ) {
148
+ LOG_WRN ("Failed to setup the signal on %s output endpoint" , uvc_host -> name );
149
+ timeout = K_MSEC (10 );
150
+ }
151
+
152
+ /* Wait for UVC device connection event */
153
+ while (true) {
154
+ err = k_poll (evt , ARRAY_SIZE (evt ), timeout );
155
+ if (err != 0 ) {
156
+ LOG_WRN ("Poll failed with error %d, retrying..." , err );
157
+ continue ;
158
+ }
159
+
160
+ int signaled , result ;
161
+ k_poll_signal_check (& sig , & signaled , & result );
162
+
163
+ if (signaled && result == USBH_DEVICE_CONNECTED ) {
164
+ LOG_INF ("UVC device connected successfully!" );
165
+ k_poll_signal_reset (& sig );
166
+ break ;
167
+ }
168
+
169
+ /* Received other signal, reset and continue waiting */
170
+ k_poll_signal_reset (& sig );
171
+ LOG_DBG ("Received signal %d, waiting for device connection..." , result );
172
+ }
126
173
127
174
/* Get capabilities */
128
175
caps .type = type ;
129
- if (video_get_caps (video_dev , & caps )) {
176
+ if (video_get_caps (uvc_host , & caps )) {
130
177
LOG_ERR ("Unable to retrieve video capabilities" );
131
178
return 0 ;
132
179
}
@@ -144,7 +191,7 @@ int main(void)
144
191
145
192
/* Get default/native format */
146
193
fmt .type = type ;
147
- if (video_get_format (video_dev , & fmt )) {
194
+ if (video_get_format (uvc_host , & fmt )) {
148
195
LOG_ERR ("Unable to retrieve video format" );
149
196
return 0 ;
150
197
}
@@ -156,7 +203,7 @@ int main(void)
156
203
sel .rect .top = CONFIG_VIDEO_SOURCE_CROP_TOP ;
157
204
sel .rect .width = CONFIG_VIDEO_SOURCE_CROP_WIDTH ;
158
205
sel .rect .height = CONFIG_VIDEO_SOURCE_CROP_HEIGHT ;
159
- if (video_set_selection (video_dev , & sel )) {
206
+ if (video_set_selection (uvc_host , & sel )) {
160
207
LOG_ERR ("Unable to set selection crop" );
161
208
return 0 ;
162
209
}
@@ -178,7 +225,7 @@ int main(void)
178
225
* and if compose is necessary
179
226
*/
180
227
sel .target = VIDEO_SEL_TGT_CROP ;
181
- err = video_get_selection (video_dev , & sel );
228
+ err = video_get_selection (uvc_host , & sel );
182
229
if (err < 0 && err != - ENOSYS ) {
183
230
LOG_ERR ("Unable to get selection crop" );
184
231
return 0 ;
@@ -190,7 +237,7 @@ int main(void)
190
237
sel .rect .top = 0 ;
191
238
sel .rect .width = fmt .width ;
192
239
sel .rect .height = fmt .height ;
193
- err = video_set_selection (video_dev , & sel );
240
+ err = video_set_selection (uvc_host , & sel );
194
241
if (err < 0 && err != - ENOSYS ) {
195
242
LOG_ERR ("Unable to set selection compose" );
196
243
return 0 ;
@@ -201,24 +248,31 @@ int main(void)
201
248
if (strcmp (CONFIG_VIDEO_PIXEL_FORMAT , "" )) {
202
249
fmt .pixelformat = VIDEO_FOURCC_FROM_STR (CONFIG_VIDEO_PIXEL_FORMAT );
203
250
}
251
+ #if CONFIG_VIDEO_FRAME_WIDTH > 0
252
+ fmt .width = CONFIG_VIDEO_FRAME_WIDTH ;
253
+ #endif
254
+
255
+ #if CONFIG_VIDEO_FRAME_HEIGHT > 0
256
+ fmt .height = CONFIG_VIDEO_FRAME_HEIGHT ;
257
+ #endif
204
258
205
259
LOG_INF ("- Video format: %s %ux%u" ,
206
260
VIDEO_FOURCC_TO_STR (fmt .pixelformat ), fmt .width , fmt .height );
207
261
208
- if (video_set_format (video_dev , & fmt )) {
262
+ if (video_set_format (uvc_host , & fmt )) {
209
263
LOG_ERR ("Unable to set format" );
210
264
return 0 ;
211
265
}
212
266
213
- if (!video_get_frmival (video_dev , & frmival )) {
267
+ if (!video_get_frmival (uvc_host , & frmival )) {
214
268
LOG_INF ("- Default frame rate : %f fps" ,
215
269
1.0 * frmival .denominator / frmival .numerator );
216
270
}
217
271
218
272
LOG_INF ("- Supported frame intervals for the default format:" );
219
273
memset (& fie , 0 , sizeof (fie ));
220
274
fie .format = & fmt ;
221
- while (video_enum_frmival (video_dev , & fie ) == 0 ) {
275
+ while (video_enum_frmival (uvc_host , & fie ) == 0 ) {
222
276
if (fie .type == VIDEO_FRMIVAL_TYPE_DISCRETE ) {
223
277
LOG_INF (" %u/%u" , fie .discrete .numerator , fie .discrete .denominator );
224
278
} else {
@@ -233,7 +287,7 @@ int main(void)
233
287
/* Get supported controls */
234
288
LOG_INF ("- Supported controls:" );
235
289
const struct device * last_dev = NULL ;
236
- struct video_ctrl_query cq = {.dev = video_dev , .id = VIDEO_CTRL_FLAG_NEXT_CTRL };
290
+ struct video_ctrl_query cq = {.dev = uvc_host , .id = VIDEO_CTRL_FLAG_NEXT_CTRL };
237
291
238
292
while (!video_query_ctrl (& cq )) {
239
293
if (cq .dev != last_dev ) {
@@ -249,17 +303,17 @@ int main(void)
249
303
int tp_set_ret = - ENOTSUP ;
250
304
251
305
if (IS_ENABLED (CONFIG_VIDEO_CTRL_HFLIP )) {
252
- video_set_ctrl (video_dev , & ctrl );
306
+ video_set_ctrl (uvc_host , & ctrl );
253
307
}
254
308
255
309
if (IS_ENABLED (CONFIG_VIDEO_CTRL_VFLIP )) {
256
310
ctrl .id = VIDEO_CID_VFLIP ;
257
- video_set_ctrl (video_dev , & ctrl );
311
+ video_set_ctrl (uvc_host , & ctrl );
258
312
}
259
313
260
314
if (IS_ENABLED (CONFIG_TEST )) {
261
315
ctrl .id = VIDEO_CID_TEST_PATTERN ;
262
- tp_set_ret = video_set_ctrl (video_dev , & ctrl );
316
+ video_set_ctrl (uvc_host , & ctrl );
263
317
}
264
318
265
319
#if DT_HAS_CHOSEN (zephyr_display )
@@ -273,8 +327,10 @@ int main(void)
273
327
err = display_setup (display_dev , fmt .pixelformat );
274
328
if (err ) {
275
329
LOG_ERR ("Unable to set up display" );
330
+ /* TODO: Use the format that this display supported, then need to do format covertion when streaming */
276
331
return err ;
277
332
}
333
+
278
334
#endif
279
335
280
336
/* Size to allocate for each buffer */
@@ -284,6 +340,12 @@ int main(void)
284
340
bsize = fmt .pitch * caps .min_line_count ;
285
341
}
286
342
343
+ /* Start video capture */
344
+ if (video_stream_start (uvc_host , type )) {
345
+ LOG_ERR ("Unable to start capture (interface)" );
346
+ return 0 ;
347
+ }
348
+
287
349
/* Alloc video buffers and enqueue for capture */
288
350
for (i = 0 ; i < ARRAY_SIZE (buffers ); i ++ ) {
289
351
/*
@@ -297,21 +359,20 @@ int main(void)
297
359
return 0 ;
298
360
}
299
361
buffers [i ]-> type = type ;
300
- video_enqueue (video_dev , buffers [i ]);
301
- }
302
-
303
- /* Start video capture */
304
- if (video_stream_start (video_dev , type )) {
305
- LOG_ERR ("Unable to start capture (interface)" );
306
- return 0 ;
362
+ video_enqueue (uvc_host , buffers [i ]);
307
363
}
308
364
309
365
LOG_INF ("Capture started" );
310
366
311
367
/* Grab video frames */
312
368
vbuf -> type = type ;
313
369
while (1 ) {
314
- err = video_dequeue (video_dev , & vbuf , K_FOREVER );
370
+ err = k_poll (evt , ARRAY_SIZE (evt ), timeout );
371
+ if (err != 0 && err != - EAGAIN ) {
372
+ LOG_ERR ("Poll exited with status %d" , err );
373
+ return err ;
374
+ }
375
+ err = video_dequeue (uvc_host , & vbuf , K_FOREVER );
315
376
if (err ) {
316
377
LOG_ERR ("Unable to dequeue video buf" );
317
378
return 0 ;
@@ -329,13 +390,15 @@ int main(void)
329
390
#endif
330
391
331
392
#if DT_HAS_CHOSEN (zephyr_display )
393
+ vbuf -> type = VIDEO_BUF_TYPE_INPUT ;
332
394
video_display_frame (display_dev , vbuf , fmt );
333
395
#endif
334
-
335
- err = video_enqueue (video_dev , vbuf );
396
+ err = video_enqueue (uvc_host , vbuf );
336
397
if (err ) {
337
398
LOG_ERR ("Unable to requeue video buf" );
338
399
return 0 ;
339
400
}
401
+
402
+ video_uvc_device_signal_handler ();
340
403
}
341
404
}
0 commit comments