Explorar o código

feat(class/video/usbh_video): support bulk mode

Signed-off-by: sakumisu <1203593632@qq.com>
sakumisu hai 3 meses
pai
achega
6c239e175f
Modificáronse 2 ficheiros con 77 adicións e 66 borrados
  1. 74 64
      class/video/usbh_video.c
  2. 3 2
      class/video/usbh_video.h

+ 74 - 64
class/video/usbh_video.c

@@ -122,12 +122,12 @@ int usbh_videostreaming_get_cur_probe(struct usbh_video *video_class)
     return usbh_video_get(video_class, VIDEO_REQUEST_GET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
 }
 
-int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex)
+int usbh_videostreaming_set_cur_probe(struct usbh_video *video_class, uint8_t formatindex, uint8_t frameindex, uint32_t dwFrameInterval)
 {
     video_class->probe.bFormatIndex = formatindex;
     video_class->probe.bFrameIndex = frameindex;
     video_class->probe.dwMaxPayloadTransferSize = 0;
-    video_class->probe.dwFrameInterval = 333333;
+    video_class->probe.dwFrameInterval = dwFrameInterval;
     return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_PROBE_CONTROL, (uint8_t *)&video_class->probe, 26);
 }
 
@@ -136,7 +136,6 @@ int usbh_videostreaming_set_cur_commit(struct usbh_video *video_class, uint8_t f
     memcpy(&video_class->commit, &video_class->probe, sizeof(struct video_probe_and_commit_controls));
     video_class->commit.bFormatIndex = formatindex;
     video_class->commit.bFrameIndex = frameindex;
-    video_class->commit.dwFrameInterval = 333333;
     return usbh_video_set(video_class, VIDEO_REQUEST_SET_CUR, video_class->data_intf, 0x00, VIDEO_VS_COMMIT_CONTROL, (uint8_t *)&video_class->commit, 26);
 }
 
@@ -154,6 +153,7 @@ int usbh_video_open(struct usbh_video *video_class,
     bool found = false;
     uint8_t formatidx = 0;
     uint8_t frameidx = 0;
+    uint32_t dwDefaultFrameInterval = 0;
     uint8_t step;
 
     if (!video_class || !video_class->hport) {
@@ -172,6 +172,7 @@ int usbh_video_open(struct usbh_video *video_class,
                 if ((wWidth == video_class->format[i].frame[j].wWidth) &&
                     (wHeight == video_class->format[i].frame[j].wHeight)) {
                     frameidx = j + 1;
+                    dwDefaultFrameInterval = video_class->format[i].frame[j].dwDefaultFrameInterval;
                     found = true;
                     break;
                 }
@@ -204,7 +205,7 @@ int usbh_video_open(struct usbh_video *video_class,
     }
 
     step = 1;
-    ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
+    ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx, dwDefaultFrameInterval);
     if (ret < 0) {
         goto errout;
     }
@@ -228,7 +229,7 @@ int usbh_video_open(struct usbh_video *video_class,
     }
 
     step = 5;
-    ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx);
+    ret = usbh_videostreaming_set_cur_probe(video_class, formatidx, frameidx, dwDefaultFrameInterval);
     if (ret < 0) {
         goto errout;
     }
@@ -246,26 +247,30 @@ int usbh_video_open(struct usbh_video *video_class,
     }
 
     step = 8;
-    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
-    setup->bRequest = USB_REQUEST_SET_INTERFACE;
-    setup->wValue = altsetting;
-    setup->wIndex = video_class->data_intf;
-    setup->wLength = 0;
-
-    ret = usbh_control_transfer(video_class->hport, setup, NULL);
-    if (ret < 0) {
-        goto errout;
-    }
+    if (!video_class->is_bulk) {
+        setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
+        setup->bRequest = USB_REQUEST_SET_INTERFACE;
+        setup->wValue = altsetting;
+        setup->wIndex = video_class->data_intf;
+        setup->wLength = 0;
+
+        ret = usbh_control_transfer(video_class->hport, setup, NULL);
+        if (ret < 0) {
+            goto errout;
+        }
 
-    ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
-    mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
-    mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
-    if (ep_desc->bEndpointAddress & 0x80) {
-        video_class->isoin_mps = mps * (mult + 1);
-        USBH_EP_INIT(video_class->isoin, ep_desc);
+        ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[altsetting].ep[0].ep_desc;
+        mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
+        mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
+        if (ep_desc->bEndpointAddress & 0x80) {
+            video_class->isoin_mps = mps * (mult + 1);
+            USBH_EP_INIT(video_class->isoin, ep_desc);
+        } else {
+            return -USB_ERR_NODEV;
+        }
     } else {
-        video_class->isoout_mps = mps * (mult + 1);
-        USBH_EP_INIT(video_class->isoout, ep_desc);
+        ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[0].ep[0].ep_desc;
+        USBH_EP_INIT(video_class->bulkin, ep_desc);
     }
 
     USB_LOG_INFO("Open video and select formatidx:%u, frameidx:%u, altsetting:%u\r\n", formatidx, frameidx, altsetting);
@@ -292,54 +297,62 @@ int usbh_video_close(struct usbh_video *video_class)
 
     video_class->is_opened = false;
 
-    if (video_class->isoin) {
-        video_class->isoin = NULL;
-    }
-
-    if (video_class->isoout) {
-        video_class->isoout = NULL;
+    if (video_class->is_bulk) {
+        setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_ENDPOINT;
+        setup->bRequest = USB_REQUEST_CLEAR_FEATURE;
+        setup->wValue = USB_FEATURE_ENDPOINT_HALT;
+        setup->wIndex = video_class->bulkin->bEndpointAddress;
+        setup->wLength = 0;
+    } else {
+        setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
+        setup->bRequest = USB_REQUEST_SET_INTERFACE;
+        setup->wValue = 0;
+        setup->wIndex = video_class->data_intf;
+        setup->wLength = 0;
     }
 
-    setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
-    setup->bRequest = USB_REQUEST_SET_INTERFACE;
-    setup->wValue = 0;
-    setup->wIndex = video_class->data_intf;
-    setup->wLength = 0;
-
     ret = usbh_control_transfer(video_class->hport, setup, NULL);
     if (ret < 0) {
         return ret;
     }
+
     return ret;
 }
 
 void usbh_video_list_info(struct usbh_video *video_class)
 {
     struct usb_endpoint_descriptor *ep_desc;
-    uint8_t mult;
-    uint16_t mps;
 
     USB_LOG_INFO("============= Video device information ===================\r\n");
     USB_LOG_RAW("bcdVDC:%04x\r\n", video_class->bcdVDC);
-    USB_LOG_RAW("Num of altsettings:%u\r\n", video_class->num_of_intf_altsettings);
-
-    for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
-        if (i == 0) {
-            USB_LOG_RAW("Ingore altsetting 0\r\n");
-            continue;
+    USB_LOG_RAW("Num of altsettings:%u (%s mode)\r\n", video_class->num_of_intf_altsettings, video_class->num_of_intf_altsettings == 1 ? "bulk" : "iso");
+
+    video_class->is_bulk = video_class->num_of_intf_altsettings == 1 ? true : false;
+
+    if (video_class->is_bulk) {
+        ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[0].ep[0].ep_desc;
+        USB_LOG_RAW("Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
+                    ep_desc->bEndpointAddress,
+                    ep_desc->bmAttributes,
+                    USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize),
+                    ep_desc->bInterval,
+                    USB_GET_MULT(ep_desc->wMaxPacketSize));
+    } else {
+        for (uint8_t i = 0; i < video_class->num_of_intf_altsettings; i++) {
+            if (i == 0) {
+                USB_LOG_RAW("Ingore altsetting 0\r\n");
+                continue;
+            }
+            ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
+
+            USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
+                        i,
+                        ep_desc->bEndpointAddress,
+                        ep_desc->bmAttributes,
+                        USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize),
+                        ep_desc->bInterval,
+                        USB_GET_MULT(ep_desc->wMaxPacketSize));
         }
-        ep_desc = &video_class->hport->config.intf[video_class->data_intf].altsetting[i].ep[0].ep_desc;
-
-        mult = (ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_MASK) >> USB_MAXPACKETSIZE_ADDITIONAL_TRANSCATION_SHIFT;
-        mps = ep_desc->wMaxPacketSize & USB_MAXPACKETSIZE_MASK;
-
-        USB_LOG_RAW("Altsetting:%u, Ep=%02x Attr=%02u Mps=%d Interval=%02u Mult=%02u\r\n",
-                     i,
-                     ep_desc->bEndpointAddress,
-                     ep_desc->bmAttributes,
-                     mps,
-                     ep_desc->bInterval,
-                     mult);
     }
 
     USB_LOG_RAW("bNumFormats:%u\r\n", video_class->num_of_formats);
@@ -350,9 +363,10 @@ void usbh_video_list_info(struct usbh_video *video_class)
         USB_LOG_RAW("  Resolution:\r\n");
         for (uint8_t j = 0; j < video_class->format[i].num_of_frames; j++) {
             USB_LOG_RAW("      FrameIndex:%u\r\n", j + 1);
-            USB_LOG_RAW("      wWidth: %d, wHeight: %d\r\n",
-                         video_class->format[i].frame[j].wWidth,
-                         video_class->format[i].frame[j].wHeight);
+            USB_LOG_RAW("      wWidth: %d, wHeight: %d, fps: %d\r\n",
+                        video_class->format[i].frame[j].wWidth,
+                        video_class->format[i].frame[j].wHeight,
+                        (1000 / (video_class->format[i].frame[j].dwDefaultFrameInterval / 10000)));
         }
     }
 
@@ -438,12 +452,14 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
 
                             video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wWidth;
                             video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->wHeight;
+                            video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval;
                             break;
                         case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE:
                             frame_index = p[DESC_bFrameIndex];
 
                             video_class->format[format_index - 1].frame[frame_index - 1].wWidth = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wWidth;
                             video_class->format[format_index - 1].frame[frame_index - 1].wHeight = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->wHeight;
+                            video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->dwDefaultFrameInterval;
                             break;
                         default:
                             break;
@@ -476,12 +492,6 @@ static int usbh_video_ctrl_disconnect(struct usbh_hubport *hport, uint8_t intf)
     struct usbh_video *video_class = (struct usbh_video *)hport->config.intf[intf].priv;
 
     if (video_class) {
-        if (video_class->isoin) {
-        }
-
-        if (video_class->isoout) {
-        }
-
         if (hport->config.intf[intf].devname[0] != '\0') {
             usb_osal_thread_schedule_other();
             USB_LOG_INFO("Unregister Video Class:%s\r\n", hport->config.intf[intf].devname);

+ 3 - 2
class/video/usbh_video.h

@@ -14,6 +14,7 @@
 struct usbh_video_resolution {
     uint16_t wWidth;
     uint16_t wHeight;
+    uint32_t dwDefaultFrameInterval;
 };
 
 struct usbh_video_format {
@@ -40,7 +41,7 @@ struct usbh_videostreaming {
 struct usbh_video {
     struct usbh_hubport *hport;
     struct usb_endpoint_descriptor *isoin;  /* ISO IN endpoint */
-    struct usb_endpoint_descriptor *isoout; /* ISO OUT endpoint */
+    struct usb_endpoint_descriptor *bulkin;  /* Bulk IN endpoint */
 
     uint8_t ctrl_intf; /* interface number */
     uint8_t data_intf; /* interface number */
@@ -48,9 +49,9 @@ struct usbh_video {
     struct video_probe_and_commit_controls probe;
     struct video_probe_and_commit_controls commit;
     uint16_t isoin_mps;
-    uint16_t isoout_mps;
     bool is_opened;
     uint8_t current_format;
+    bool is_bulk;
     uint16_t bcdVDC;
     uint8_t num_of_intf_altsettings;
     uint8_t num_of_formats;