rtt更新
This commit is contained in:
@@ -18,12 +18,28 @@ struct usbd_video_priv {
|
||||
uint8_t power_mode;
|
||||
uint8_t error_code;
|
||||
struct video_entity_info info[3];
|
||||
uint8_t *ep_buf0;
|
||||
uint8_t *ep_buf1;
|
||||
bool ep_buf0_ready;
|
||||
bool ep_buf1_ready;
|
||||
uint32_t ep_buf0_len;
|
||||
uint32_t ep_buf1_len;
|
||||
uint8_t ep_buf_idx;
|
||||
bool stream_finish;
|
||||
uint32_t max_packets;
|
||||
uint8_t *stream_buf;
|
||||
uint32_t stream_len;
|
||||
uint32_t stream_offset;
|
||||
uint8_t stream_frameid;
|
||||
uint32_t stream_headerlen;
|
||||
} g_usbd_video[CONFIG_USBDEV_MAX_BUS];
|
||||
|
||||
static int usbd_video_control_request_handler(uint8_t busid, struct usb_setup_packet *setup, uint8_t **data, uint32_t *len)
|
||||
{
|
||||
uint8_t control_selector = (uint8_t)(setup->wValue >> 8);
|
||||
|
||||
(void)busid;
|
||||
|
||||
switch (control_selector) {
|
||||
case VIDEO_VC_VIDEO_POWER_MODE_CONTROL:
|
||||
switch (setup->bRequest) {
|
||||
@@ -669,7 +685,7 @@ static int video_class_interface_request_handler(uint8_t busid, struct usb_setup
|
||||
} else {
|
||||
return usbd_video_control_unit_terminal_request_handler(busid, setup, data, len); /* Unit and Terminal Requests */
|
||||
}
|
||||
} else if (intf_num == 1) { /* Video Stream Inteface */
|
||||
} else if (intf_num == 1) { /* Video Stream Inteface */
|
||||
return usbd_video_stream_request_handler(busid, setup, data, len); /* Interface Stream Requests */
|
||||
}
|
||||
return -1;
|
||||
@@ -698,7 +714,7 @@ static void video_notify_handler(uint8_t busid, uint8_t event, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
static void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameInterval, uint32_t dwMaxVideoFrameSize, uint32_t dwMaxPayloadTransferSize)
|
||||
{
|
||||
g_usbd_video[busid].probe.hintUnion.bmHint = 0x01;
|
||||
g_usbd_video[busid].probe.hintUnion1.bmHint = 0;
|
||||
@@ -735,9 +751,47 @@ void usbd_video_probe_and_commit_controls_init(uint8_t busid, uint32_t dwFrameIn
|
||||
g_usbd_video[busid].commit.bPreferedVersion = 0;
|
||||
g_usbd_video[busid].commit.bMinVersion = 0;
|
||||
g_usbd_video[busid].commit.bMaxVersion = 0;
|
||||
|
||||
g_usbd_video[busid].stream_frameid = 0;
|
||||
g_usbd_video[busid].stream_headerlen = 2;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface *intf,
|
||||
static uint32_t usbd_video_prepare_ep_buf_data(uint8_t busid, uint32_t remain, uint8_t *ep_buf)
|
||||
{
|
||||
struct video_payload_header *header;
|
||||
uint32_t len;
|
||||
uint32_t offset;
|
||||
|
||||
len = MIN(remain, (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen) * g_usbd_video[busid].max_packets);
|
||||
offset = 0;
|
||||
while (len > 0) {
|
||||
header = (struct video_payload_header *)&ep_buf[offset];
|
||||
header->bHeaderLength = g_usbd_video[busid].stream_headerlen;
|
||||
header->headerInfoUnion.bmheaderInfo = 0;
|
||||
header->headerInfoUnion.headerInfoBits.endOfHeader = 1;
|
||||
header->headerInfoUnion.headerInfoBits.endOfFrame = 0;
|
||||
header->headerInfoUnion.headerInfoBits.frameIdentifier = g_usbd_video[busid].stream_frameid;
|
||||
|
||||
uint32_t len2 = MIN(len, g_usbd_video[busid].probe.dwMaxPayloadTransferSize - g_usbd_video[busid].stream_headerlen);
|
||||
|
||||
usb_memcpy(&ep_buf[offset + g_usbd_video[busid].stream_headerlen],
|
||||
&g_usbd_video[busid].stream_buf[g_usbd_video[busid].stream_offset],
|
||||
len2);
|
||||
|
||||
g_usbd_video[busid].stream_offset += len2;
|
||||
len -= len2;
|
||||
offset += (len2 + g_usbd_video[busid].stream_headerlen);
|
||||
|
||||
if (g_usbd_video[busid].stream_offset == g_usbd_video[busid].stream_len) {
|
||||
header->headerInfoUnion.headerInfoBits.endOfFrame = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
struct usbd_interface *usbd_video_init_intf(uint8_t busid,
|
||||
struct usbd_interface *intf,
|
||||
uint32_t dwFrameInterval,
|
||||
uint32_t dwMaxVideoFrameSize,
|
||||
uint32_t dwMaxPayloadTransferSize)
|
||||
@@ -761,28 +815,70 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
|
||||
return intf;
|
||||
}
|
||||
|
||||
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len)
|
||||
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep)
|
||||
{
|
||||
uint32_t packets;
|
||||
uint32_t last_packet_size;
|
||||
uint32_t picture_pos = 0;
|
||||
static uint8_t uvc_header[2] = { 0x02, 0x80 };
|
||||
uint32_t remain;
|
||||
|
||||
packets = (input_len + (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2) ) / (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||
last_packet_size = input_len - ((packets - 1) * (g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2));
|
||||
|
||||
for (size_t i = 0; i < packets; i++) {
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i] = uvc_header[0];
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] = uvc_header[1];
|
||||
if (i == (packets - 1)) {
|
||||
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], last_packet_size);
|
||||
output[g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i + 1] |= (1 << 1);
|
||||
} else {
|
||||
memcpy(&output[2 + g_usbd_video[busid].probe.dwMaxPayloadTransferSize * i], &input[picture_pos], g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2);
|
||||
picture_pos += g_usbd_video[busid].probe.dwMaxPayloadTransferSize - 2;
|
||||
if (g_usbd_video[busid].ep_buf1_ready && (g_usbd_video[busid].ep_buf_idx == 0)) { /* callback: buf1 ready and buf0 was sent */
|
||||
g_usbd_video[busid].ep_buf0_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 1;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf1, g_usbd_video[busid].ep_buf1_len);
|
||||
} else if (g_usbd_video[busid].ep_buf0_ready && (g_usbd_video[busid].ep_buf_idx == 1)) { /* callback: buf0 ready and buf1 was sent */
|
||||
g_usbd_video[busid].ep_buf1_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
|
||||
} else {
|
||||
if (g_usbd_video[busid].stream_finish) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
uvc_header[1] ^= 1;
|
||||
*out_len = (input_len + 2 * packets);
|
||||
return packets;
|
||||
}
|
||||
|
||||
if (!g_usbd_video[busid].ep_buf0_ready) {
|
||||
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
|
||||
if (remain == 0) {
|
||||
g_usbd_video[busid].stream_frameid ^= 1;
|
||||
g_usbd_video[busid].stream_finish = true;
|
||||
} else {
|
||||
g_usbd_video[busid].ep_buf0_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf0);
|
||||
g_usbd_video[busid].ep_buf0_ready = true;
|
||||
if (!g_usbd_video[busid].ep_buf1_ready) {
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
usbd_ep_start_write(busid, ep, g_usbd_video[busid].ep_buf0, g_usbd_video[busid].ep_buf0_len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!g_usbd_video[busid].ep_buf1_ready) {
|
||||
remain = g_usbd_video[busid].stream_len - g_usbd_video[busid].stream_offset;
|
||||
if (remain == 0) {
|
||||
g_usbd_video[busid].stream_frameid ^= 1;
|
||||
g_usbd_video[busid].stream_finish = true;
|
||||
} else {
|
||||
g_usbd_video[busid].ep_buf1_len = usbd_video_prepare_ep_buf_data(busid, remain, g_usbd_video[busid].ep_buf1);
|
||||
g_usbd_video[busid].ep_buf1_ready = true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len)
|
||||
{
|
||||
if ((usb_device_is_configured(busid) == 0) || (stream_len == 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
g_usbd_video[busid].ep_buf0 = ep_buf0;
|
||||
g_usbd_video[busid].ep_buf1 = ep_buf1;
|
||||
g_usbd_video[busid].ep_buf0_ready = false;
|
||||
g_usbd_video[busid].ep_buf1_ready = false;
|
||||
g_usbd_video[busid].ep_buf_idx = 0;
|
||||
g_usbd_video[busid].stream_finish = false;
|
||||
g_usbd_video[busid].max_packets = ep_bufsize / g_usbd_video[busid].probe.dwMaxPayloadTransferSize;
|
||||
g_usbd_video[busid].stream_buf = stream_buf;
|
||||
g_usbd_video[busid].stream_len = stream_len;
|
||||
g_usbd_video[busid].stream_offset = 0;
|
||||
|
||||
usbd_video_stream_split_transfer(busid, ep);
|
||||
return 0;
|
||||
}
|
||||
|
@@ -20,7 +20,9 @@ struct usbd_interface *usbd_video_init_intf(uint8_t busid, struct usbd_interface
|
||||
|
||||
void usbd_video_open(uint8_t busid, uint8_t intf);
|
||||
void usbd_video_close(uint8_t busid, uint8_t intf);
|
||||
uint32_t usbd_video_payload_fill(uint8_t busid, uint8_t *input, uint32_t input_len, uint8_t *output, uint32_t *out_len);
|
||||
|
||||
bool usbd_video_stream_split_transfer(uint8_t busid, uint8_t ep);
|
||||
int usbd_video_stream_start_write(uint8_t busid, uint8_t ep, uint8_t *ep_buf0, uint8_t *ep_buf1, uint32_t ep_bufsize, uint8_t *stream_buf, uint32_t stream_len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@@ -34,11 +34,11 @@ static uint32_t g_devinuse = 0;
|
||||
|
||||
static struct usbh_video *usbh_video_class_alloc(void)
|
||||
{
|
||||
int devno;
|
||||
uint8_t devno;
|
||||
|
||||
for (devno = 0; devno < CONFIG_USBHOST_MAX_VIDEO_CLASS; devno++) {
|
||||
if ((g_devinuse & (1 << devno)) == 0) {
|
||||
g_devinuse |= (1 << devno);
|
||||
if ((g_devinuse & (1U << devno)) == 0) {
|
||||
g_devinuse |= (1U << devno);
|
||||
memset(&g_video_class[devno], 0, sizeof(struct usbh_video));
|
||||
g_video_class[devno].minor = devno;
|
||||
return &g_video_class[devno];
|
||||
@@ -49,10 +49,10 @@ static struct usbh_video *usbh_video_class_alloc(void)
|
||||
|
||||
static void usbh_video_class_free(struct usbh_video *video_class)
|
||||
{
|
||||
int devno = video_class->minor;
|
||||
uint8_t devno = video_class->minor;
|
||||
|
||||
if (devno >= 0 && devno < 32) {
|
||||
g_devinuse &= ~(1 << devno);
|
||||
if (devno < 32) {
|
||||
g_devinuse &= ~(1U << devno);
|
||||
}
|
||||
memset(video_class, 0, sizeof(struct usbh_video));
|
||||
}
|
||||
@@ -495,20 +495,26 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
|
||||
static int usbh_video_streaming_connect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int usbh_video_streaming_disconnect(struct usbh_hubport *hport, uint8_t intf)
|
||||
{
|
||||
(void)hport;
|
||||
(void)intf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_run(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
__WEAK void usbh_video_stop(struct usbh_video *video_class)
|
||||
{
|
||||
(void)video_class;
|
||||
}
|
||||
|
||||
const struct usbh_class_driver video_ctrl_class_driver = {
|
||||
@@ -525,18 +531,18 @@ const struct usbh_class_driver video_streaming_class_driver = {
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_ctrl_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOCONTROL,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SC_VIDEOCONTROL,
|
||||
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.id_table = NULL,
|
||||
.class_driver = &video_ctrl_class_driver
|
||||
};
|
||||
|
||||
CLASS_INFO_DEFINE const struct usbh_class_info video_streaming_class_info = {
|
||||
.match_flags = USB_CLASS_MATCH_INTF_CLASS | USB_CLASS_MATCH_INTF_SUBCLASS | USB_CLASS_MATCH_INTF_PROTOCOL,
|
||||
.class = USB_DEVICE_CLASS_VIDEO,
|
||||
.subclass = VIDEO_SC_VIDEOSTREAMING,
|
||||
.protocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.bInterfaceClass = USB_DEVICE_CLASS_VIDEO,
|
||||
.bInterfaceSubClass = VIDEO_SC_VIDEOSTREAMING,
|
||||
.bInterfaceProtocol = VIDEO_PC_PROTOCOL_UNDEFINED,
|
||||
.id_table = NULL,
|
||||
.class_driver = &video_streaming_class_driver
|
||||
};
|
||||
|
Reference in New Issue
Block a user