1 #include "usbd_core.h"
2 #include "usbd_video.h"
3 #include "pic_data.h"
4
5 #define VIDEO_IN_EP 0x81
6
7 #ifdef CONFIG_USB_HS
8 #define MAX_PAYLOAD_SIZE 1024 // for high speed with one transcations every one micro frame
9 #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
10
11 // #define MAX_PAYLOAD_SIZE 2048 // for high speed with two transcations every one micro frame
12 // #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 2)) | (0x01 << 11))
13
14 // #define MAX_PAYLOAD_SIZE 3072 // for high speed with three transcations every one micro frame
15 // #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 3)) | (0x02 << 11))
16
17 #else
18 #define MAX_PAYLOAD_SIZE 1020
19 #define VIDEO_PACKET_SIZE (unsigned int)(((MAX_PAYLOAD_SIZE / 1)) | (0x00 << 11))
20 #endif
21
22 #define WIDTH (unsigned int)(640)
23 #define HEIGHT (unsigned int)(480)
24
25 #define CAM_FPS (30)
26 #define INTERVAL (unsigned long)(10000000 / CAM_FPS)
27 #define MIN_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS) //16 bit
28 #define MAX_BIT_RATE (unsigned long)(WIDTH * HEIGHT * 16 * CAM_FPS)
29 #define MAX_FRAME_SIZE (unsigned long)(WIDTH * HEIGHT * 2)
30
31 #define USB_VIDEO_DESC_SIZ (unsigned long)(9 + \
32 8 + \
33 9 + \
34 13 + \
35 18 + \
36 9 + \
37 12 + \
38 9 + \
39 14 + \
40 11 + \
41 30 + \
42 9 + \
43 7)
44
45 #define VC_TERMINAL_SIZ (unsigned int)(13 + 18 + 12 + 9)
46 #define VS_HEADER_SIZ (unsigned int)(13 + 1 + 11 + 30)
47
48 #define USBD_VID 0xffff
49 #define USBD_PID 0xffff
50 #define USBD_MAX_POWER 100
51 #define USBD_LANGID_STRING 1033
52
53 const uint8_t video_descriptor[] = {
54 USB_DEVICE_DESCRIPTOR_INIT(USB_2_0, 0xef, 0x02, 0x01, USBD_VID, USBD_PID, 0x0001, 0x01),
55 USB_CONFIG_DESCRIPTOR_INIT(USB_VIDEO_DESC_SIZ, 0x02, 0x01, USB_CONFIG_BUS_POWERED, USBD_MAX_POWER),
56 VIDEO_VC_DESCRIPTOR_INIT(0x00, 0, 0x0100, VC_TERMINAL_SIZ, 48000000, 0x02),
57 VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x00, 0x00),
58 VIDEO_VS_HEADER_DESCRIPTOR_INIT(0x01, VS_HEADER_SIZ, VIDEO_IN_EP, 0x00),
59 VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_INIT(0x01, 0x01),
60 VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_INIT(0x01, WIDTH, HEIGHT, MIN_BIT_RATE, MAX_BIT_RATE, MAX_FRAME_SIZE, DBVAL(INTERVAL), 0x01, DBVAL(INTERVAL)),
61 VIDEO_VS_DESCRIPTOR_INIT(0x01, 0x01, 0x01),
62 /* 1.2.2.2 Standard VideoStream Isochronous Video Data Endpoint Descriptor */
63 0x07, /* bLength */
64 USB_DESCRIPTOR_TYPE_ENDPOINT, /* bDescriptorType: ENDPOINT */
65 0x81, /* bEndpointAddress: IN endpoint 2 */
66 0x01, /* bmAttributes: Isochronous transfer type. Asynchronous synchronization type. */
67 WBVAL(VIDEO_PACKET_SIZE), /* wMaxPacketSize */
68 0x01, /* bInterval: One frame interval */
69
70 ///////////////////////////////////////
71 /// string0 descriptor
72 ///////////////////////////////////////
73 USB_LANGID_INIT(USBD_LANGID_STRING),
74 ///////////////////////////////////////
75 /// string1 descriptor
76 ///////////////////////////////////////
77 0x14, /* bLength */
78 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
79 'C', 0x00, /* wcChar0 */
80 'h', 0x00, /* wcChar1 */
81 'e', 0x00, /* wcChar2 */
82 'r', 0x00, /* wcChar3 */
83 'r', 0x00, /* wcChar4 */
84 'y', 0x00, /* wcChar5 */
85 'U', 0x00, /* wcChar6 */
86 'S', 0x00, /* wcChar7 */
87 'B', 0x00, /* wcChar8 */
88 ///////////////////////////////////////
89 /// string2 descriptor
90 ///////////////////////////////////////
91 0x26, /* bLength */
92 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
93 'C', 0x00, /* wcChar0 */
94 'h', 0x00, /* wcChar1 */
95 'e', 0x00, /* wcChar2 */
96 'r', 0x00, /* wcChar3 */
97 'r', 0x00, /* wcChar4 */
98 'y', 0x00, /* wcChar5 */
99 'U', 0x00, /* wcChar6 */
100 'S', 0x00, /* wcChar7 */
101 'B', 0x00, /* wcChar8 */
102 ' ', 0x00, /* wcChar9 */
103 'U', 0x00, /* wcChar10 */
104 'V', 0x00, /* wcChar11 */
105 'C', 0x00, /* wcChar12 */
106 ' ', 0x00, /* wcChar13 */
107 'D', 0x00, /* wcChar14 */
108 'E', 0x00, /* wcChar15 */
109 'M', 0x00, /* wcChar16 */
110 'O', 0x00, /* wcChar17 */
111 ///////////////////////////////////////
112 /// string3 descriptor
113 ///////////////////////////////////////
114 0x16, /* bLength */
115 USB_DESCRIPTOR_TYPE_STRING, /* bDescriptorType */
116 '2', 0x00, /* wcChar0 */
117 '0', 0x00, /* wcChar1 */
118 '2', 0x00, /* wcChar2 */
119 '1', 0x00, /* wcChar3 */
120 '0', 0x00, /* wcChar4 */
121 '3', 0x00, /* wcChar5 */
122 '1', 0x00, /* wcChar6 */
123 '0', 0x00, /* wcChar7 */
124 '0', 0x00, /* wcChar8 */
125 '0', 0x00, /* wcChar9 */
126 #ifdef CONFIG_USB_HS
127 ///////////////////////////////////////
128 /// device qualifier descriptor
129 ///////////////////////////////////////
130 0x0a,
131 USB_DESCRIPTOR_TYPE_DEVICE_QUALIFIER,
132 0x00,
133 0x02,
134 0x00,
135 0x00,
136 0x00,
137 0x40,
138 0x01,
139 0x00,
140 #endif
141 0x00
142 };
143
usbd_event_handler(uint8_t event)144 void usbd_event_handler(uint8_t event)
145 {
146 switch (event) {
147 case USBD_EVENT_RESET:
148 break;
149 case USBD_EVENT_CONNECTED:
150 break;
151 case USBD_EVENT_DISCONNECTED:
152 break;
153 case USBD_EVENT_RESUME:
154 break;
155 case USBD_EVENT_SUSPEND:
156 break;
157 case USBD_EVENT_CONFIGURED:
158 break;
159 case USBD_EVENT_SET_REMOTE_WAKEUP:
160 break;
161 case USBD_EVENT_CLR_REMOTE_WAKEUP:
162 break;
163
164 default:
165 break;
166 }
167 }
168
169 volatile bool tx_flag = 0;
170 volatile bool iso_tx_busy = false;
171
usbd_video_open(uint8_t intf)172 void usbd_video_open(uint8_t intf)
173 {
174 tx_flag = 1;
175 USB_LOG_RAW("OPEN\r\n");
176 iso_tx_busy = false;
177 }
usbd_video_close(uint8_t intf)178 void usbd_video_close(uint8_t intf)
179 {
180 USB_LOG_RAW("CLOSE\r\n");
181 tx_flag = 0;
182 iso_tx_busy = false;
183 }
184
usbd_video_iso_callback(uint8_t ep,uint32_t nbytes)185 void usbd_video_iso_callback(uint8_t ep, uint32_t nbytes)
186 {
187 USB_LOG_RAW("actual in len:%d\r\n", nbytes);
188 iso_tx_busy = false;
189 }
190
191 static struct usbd_endpoint video_in_ep = {
192 .ep_cb = usbd_video_iso_callback,
193 .ep_addr = VIDEO_IN_EP
194 };
195
196 struct usbd_interface intf0;
197 struct usbd_interface intf1;
198
video_init()199 void video_init()
200 {
201 usbd_desc_register(video_descriptor);
202 usbd_add_interface(usbd_video_init_intf(&intf0, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
203 usbd_add_interface(usbd_video_init_intf(&intf1, INTERVAL, MAX_FRAME_SIZE, MAX_PAYLOAD_SIZE));
204 usbd_add_endpoint(&video_in_ep);
205
206 usbd_initialize();
207 }
208
209 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t packet_buffer[10 * 1024];
210
video_test()211 void video_test()
212 {
213 uint32_t out_len;
214 uint32_t packets;
215 memset(packet_buffer, 0, 10 * 1024);
216 while (1) {
217 if (tx_flag) {
218 packets = usbd_video_mjpeg_payload_fill((uint8_t *)jpeg_data, sizeof(jpeg_data), packet_buffer, &out_len);
219 #if 0
220 iso_tx_busy = true;
221 usbd_ep_start_write(VIDEO_IN_EP, packet_buffer, out_len);
222 while (iso_tx_busy) {
223 if (tx_flag == 0) {
224 break;
225 }
226 }
227 #else
228 /* dwc2 must use this method */
229 for (uint32_t i = 0; i < packets; i++) {
230 if (i == (packets - 1)) {
231 iso_tx_busy = true;
232 usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], out_len - (packets - 1) * MAX_PAYLOAD_SIZE);
233 while (iso_tx_busy) {
234 if (tx_flag == 0) {
235 break;
236 }
237 }
238 } else {
239 iso_tx_busy = true;
240 usbd_ep_start_write(VIDEO_IN_EP, &packet_buffer[i * MAX_PAYLOAD_SIZE], MAX_PAYLOAD_SIZE);
241 while (iso_tx_busy) {
242 if (tx_flag == 0) {
243 break;
244 }
245 }
246 }
247 }
248 #endif
249 }
250 }
251 }