• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }