| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: uvideo.c,v 1.65 2022/03/03 06:21:50 riastradh Exp $ */ | | 1 | /* $NetBSD: uvideo.c,v 1.66 2022/03/03 06:22:03 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2008 Patrick Mahoney | | 4 | * Copyright (c) 2008 Patrick Mahoney |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code was written by Patrick Mahoney (pat@polycrystal.org) as | | 7 | * This code was written by Patrick Mahoney (pat@polycrystal.org) as |
8 | * part of Google Summer of Code 2008. | | 8 | * part of Google Summer of Code 2008. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
| @@ -32,27 +32,27 @@ | | | @@ -32,27 +32,27 @@ |
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
36 | * POSSIBILITY OF SUCH DAMAGE. | | 36 | * POSSIBILITY OF SUCH DAMAGE. |
37 | */ | | 37 | */ |
38 | | | 38 | |
39 | /* | | 39 | /* |
40 | * USB video specs: | | 40 | * USB video specs: |
41 | * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip | | 41 | * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
45 | __KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.65 2022/03/03 06:21:50 riastradh Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.66 2022/03/03 06:22:03 riastradh Exp $"); |
46 | | | 46 | |
47 | #ifdef _KERNEL_OPT | | 47 | #ifdef _KERNEL_OPT |
48 | #include "opt_usb.h" | | 48 | #include "opt_usb.h" |
49 | #endif | | 49 | #endif |
50 | | | 50 | |
51 | #ifdef _MODULE | | 51 | #ifdef _MODULE |
52 | #include <sys/module.h> | | 52 | #include <sys/module.h> |
53 | #endif | | 53 | #endif |
54 | | | 54 | |
55 | #include <sys/param.h> | | 55 | #include <sys/param.h> |
56 | #include <sys/systm.h> | | 56 | #include <sys/systm.h> |
57 | #include <sys/kernel.h> | | 57 | #include <sys/kernel.h> |
58 | #include <sys/kmem.h> | | 58 | #include <sys/kmem.h> |
| @@ -1015,26 +1015,31 @@ uvideo_unit_free_controls(struct uvideo_ | | | @@ -1015,26 +1015,31 @@ uvideo_unit_free_controls(struct uvideo_ |
1015 | /* Initialize a stream from a Video Streaming interface | | 1015 | /* Initialize a stream from a Video Streaming interface |
1016 | * descriptor. Adds the stream to the stream_list in uvideo_softc. | | 1016 | * descriptor. Adds the stream to the stream_list in uvideo_softc. |
1017 | * This should be called once for new streams, and | | 1017 | * This should be called once for new streams, and |
1018 | * uvideo_stream_init_desc() should then be called for this and each | | 1018 | * uvideo_stream_init_desc() should then be called for this and each |
1019 | * additional interface with the same interface number. */ | | 1019 | * additional interface with the same interface number. */ |
1020 | static usbd_status | | 1020 | static usbd_status |
1021 | uvideo_stream_init(struct uvideo_stream *vs, | | 1021 | uvideo_stream_init(struct uvideo_stream *vs, |
1022 | struct uvideo_softc *sc, | | 1022 | struct uvideo_softc *sc, |
1023 | const usb_interface_descriptor_t *ifdesc) | | 1023 | const usb_interface_descriptor_t *ifdesc) |
1024 | { | | 1024 | { |
1025 | uWord len; | | 1025 | uWord len; |
1026 | usbd_status err; | | 1026 | usbd_status err; |
1027 | | | 1027 | |
| | | 1028 | DPRINTF(("%s: %s ifaceno=%d vs=%p\n", __func__, |
| | | 1029 | device_xname(sc->sc_dev), |
| | | 1030 | ifdesc->bInterfaceNumber, |
| | | 1031 | vs)); |
| | | 1032 | |
1028 | SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries); | | 1033 | SLIST_INSERT_HEAD(&sc->sc_stream_list, vs, entries); |
1029 | memset(vs, 0, sizeof(*vs)); | | 1034 | memset(vs, 0, sizeof(*vs)); |
1030 | vs->vs_parent = sc; | | 1035 | vs->vs_parent = sc; |
1031 | vs->vs_ifaceno = ifdesc->bInterfaceNumber; | | 1036 | vs->vs_ifaceno = ifdesc->bInterfaceNumber; |
1032 | vs->vs_subtype = 0; | | 1037 | vs->vs_subtype = 0; |
1033 | SIMPLEQ_INIT(&vs->vs_formats); | | 1038 | SIMPLEQ_INIT(&vs->vs_formats); |
1034 | SIMPLEQ_INIT(&vs->vs_pixel_formats); | | 1039 | SIMPLEQ_INIT(&vs->vs_pixel_formats); |
1035 | vs->vs_default_format = NULL; | | 1040 | vs->vs_default_format = NULL; |
1036 | vs->vs_current_format.priv = -1; | | 1041 | vs->vs_current_format.priv = -1; |
1037 | vs->vs_xfer_type = 0; | | 1042 | vs->vs_xfer_type = 0; |
1038 | | | 1043 | |
1039 | err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno, | | 1044 | err = usbd_device2interface_handle(sc->sc_udev, vs->vs_ifaceno, |
1040 | &vs->vs_iface); | | 1045 | &vs->vs_iface); |
| @@ -1094,26 +1099,29 @@ static usbd_status | | | @@ -1094,26 +1099,29 @@ static usbd_status |
1094 | uvideo_stream_init_desc(struct uvideo_stream *vs, | | 1099 | uvideo_stream_init_desc(struct uvideo_stream *vs, |
1095 | const usb_interface_descriptor_t *ifdesc, | | 1100 | const usb_interface_descriptor_t *ifdesc, |
1096 | usbd_desc_iter_t *iter) | | 1101 | usbd_desc_iter_t *iter) |
1097 | { | | 1102 | { |
1098 | const usb_descriptor_t *desc; | | 1103 | const usb_descriptor_t *desc; |
1099 | const uvideo_descriptor_t *uvdesc; | | 1104 | const uvideo_descriptor_t *uvdesc; |
1100 | struct uvideo_bulk_xfer *bx; | | 1105 | struct uvideo_bulk_xfer *bx; |
1101 | struct uvideo_isoc_xfer *ix; | | 1106 | struct uvideo_isoc_xfer *ix; |
1102 | struct uvideo_alternate *alt; | | 1107 | struct uvideo_alternate *alt; |
1103 | uint8_t xfer_type, xfer_dir; | | 1108 | uint8_t xfer_type, xfer_dir; |
1104 | uint8_t bmAttributes, bEndpointAddress; | | 1109 | uint8_t bmAttributes, bEndpointAddress; |
1105 | int i; | | 1110 | int i; |
1106 | | | 1111 | |
| | | 1112 | DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d\n", __func__, |
| | | 1113 | ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); |
| | | 1114 | |
1107 | /* Iterate until the next interface descriptor. All | | 1115 | /* Iterate until the next interface descriptor. All |
1108 | * descriptors until then belong to this streaming | | 1116 | * descriptors until then belong to this streaming |
1109 | * interface. */ | | 1117 | * interface. */ |
1110 | while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { | | 1118 | while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { |
1111 | uvdesc = (const uvideo_descriptor_t *)desc; | | 1119 | uvdesc = (const uvideo_descriptor_t *)desc; |
1112 | | | 1120 | |
1113 | switch (uvdesc->bDescriptorType) { | | 1121 | switch (uvdesc->bDescriptorType) { |
1114 | case UDESC_ENDPOINT: | | 1122 | case UDESC_ENDPOINT: |
1115 | bmAttributes = GET(usb_endpoint_descriptor_t, | | 1123 | bmAttributes = GET(usb_endpoint_descriptor_t, |
1116 | desc, bmAttributes); | | 1124 | desc, bmAttributes); |
1117 | bEndpointAddress = GET(usb_endpoint_descriptor_t, | | 1125 | bEndpointAddress = GET(usb_endpoint_descriptor_t, |
1118 | desc, bEndpointAddress); | | 1126 | desc, bEndpointAddress); |
1119 | xfer_type = UE_GET_XFERTYPE(bmAttributes); | | 1127 | xfer_type = UE_GET_XFERTYPE(bmAttributes); |
| @@ -1209,26 +1217,30 @@ uvideo_stream_init_desc(struct uvideo_st | | | @@ -1209,26 +1217,30 @@ uvideo_stream_init_desc(struct uvideo_st |
1209 | break; | | 1217 | break; |
1210 | } | | 1218 | } |
1211 | break; | | 1219 | break; |
1212 | default: | | 1220 | default: |
1213 | DPRINTF(("uvideo_stream_init_desc: " | | 1221 | DPRINTF(("uvideo_stream_init_desc: " |
1214 | "unknown descriptor " | | 1222 | "unknown descriptor " |
1215 | "len=%d type=0x%02x\n", | | 1223 | "len=%d type=0x%02x\n", |
1216 | uvdesc->bLength, | | 1224 | uvdesc->bLength, |
1217 | uvdesc->bDescriptorType)); | | 1225 | uvdesc->bDescriptorType)); |
1218 | break; | | 1226 | break; |
1219 | } | | 1227 | } |
1220 | } | | 1228 | } |
1221 | | | 1229 | |
| | | 1230 | DPRINTF(("%s: bInterfaceNumber=%d bAlternateSetting=%d done\n", |
| | | 1231 | __func__, |
| | | 1232 | ifdesc->bInterfaceNumber, ifdesc->bAlternateSetting)); |
| | | 1233 | |
1222 | return USBD_NORMAL_COMPLETION; | | 1234 | return USBD_NORMAL_COMPLETION; |
1223 | } | | 1235 | } |
1224 | | | 1236 | |
1225 | /* Finialize and free memory associated with this stream. */ | | 1237 | /* Finialize and free memory associated with this stream. */ |
1226 | static void | | 1238 | static void |
1227 | uvideo_stream_free(struct uvideo_stream *vs) | | 1239 | uvideo_stream_free(struct uvideo_stream *vs) |
1228 | { | | 1240 | { |
1229 | struct uvideo_alternate *alt; | | 1241 | struct uvideo_alternate *alt; |
1230 | struct uvideo_pixel_format *pixel_format; | | 1242 | struct uvideo_pixel_format *pixel_format; |
1231 | struct uvideo_format *format; | | 1243 | struct uvideo_format *format; |
1232 | | | 1244 | |
1233 | /* free linked list of alternate interfaces */ | | 1245 | /* free linked list of alternate interfaces */ |
1234 | if (vs->vs_xfer_type == UE_ISOCHRONOUS) { | | 1246 | if (vs->vs_xfer_type == UE_ISOCHRONOUS) { |
| @@ -1257,51 +1269,64 @@ uvideo_stream_free(struct uvideo_stream | | | @@ -1257,51 +1269,64 @@ uvideo_stream_free(struct uvideo_stream |
1257 | static usbd_status | | 1269 | static usbd_status |
1258 | uvideo_stream_init_frame_based_format(struct uvideo_stream *vs, | | 1270 | uvideo_stream_init_frame_based_format(struct uvideo_stream *vs, |
1259 | const uvideo_descriptor_t *format_desc, | | 1271 | const uvideo_descriptor_t *format_desc, |
1260 | usbd_desc_iter_t *iter) | | 1272 | usbd_desc_iter_t *iter) |
1261 | { | | 1273 | { |
1262 | struct uvideo_pixel_format *pformat, *pfiter; | | 1274 | struct uvideo_pixel_format *pformat, *pfiter; |
1263 | enum video_pixel_format pixel_format; | | 1275 | enum video_pixel_format pixel_format; |
1264 | struct uvideo_format *format; | | 1276 | struct uvideo_format *format; |
1265 | const uvideo_descriptor_t *uvdesc; | | 1277 | const uvideo_descriptor_t *uvdesc; |
1266 | uint8_t subtype, default_index, index; | | 1278 | uint8_t subtype, default_index, index; |
1267 | uint32_t frame_interval; | | 1279 | uint32_t frame_interval; |
1268 | const usb_guid_t *guid; | | 1280 | const usb_guid_t *guid; |
1269 | | | 1281 | |
| | | 1282 | DPRINTF(("%s: ifaceno=%d subtype=%d probelen=%d\n", __func__, |
| | | 1283 | vs->vs_ifaceno, vs->vs_subtype, vs->vs_probelen)); |
| | | 1284 | |
1270 | pixel_format = VIDEO_FORMAT_UNDEFINED; | | 1285 | pixel_format = VIDEO_FORMAT_UNDEFINED; |
1271 | | | 1286 | |
1272 | switch (format_desc->bDescriptorSubtype) { | | 1287 | switch (format_desc->bDescriptorSubtype) { |
1273 | case UDESC_VS_FORMAT_UNCOMPRESSED: | | 1288 | case UDESC_VS_FORMAT_UNCOMPRESSED: |
| | | 1289 | DPRINTF(("%s: uncompressed\n", __func__)); |
1274 | subtype = UDESC_VS_FRAME_UNCOMPRESSED; | | 1290 | subtype = UDESC_VS_FRAME_UNCOMPRESSED; |
1275 | default_index = GET(uvideo_vs_format_uncompressed_descriptor_t, | | 1291 | default_index = GET(uvideo_vs_format_uncompressed_descriptor_t, |
1276 | format_desc, | | 1292 | format_desc, |
1277 | bDefaultFrameIndex); | | 1293 | bDefaultFrameIndex); |
1278 | guid = GETP(uvideo_vs_format_uncompressed_descriptor_t, | | 1294 | guid = GETP(uvideo_vs_format_uncompressed_descriptor_t, |
1279 | format_desc, | | 1295 | format_desc, |
1280 | guidFormat); | | 1296 | guidFormat); |
1281 | if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0) | | 1297 | if (usb_guid_cmp(guid, &uvideo_guid_format_yuy2) == 0) |
1282 | pixel_format = VIDEO_FORMAT_YUY2; | | 1298 | pixel_format = VIDEO_FORMAT_YUY2; |
1283 | else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0) | | 1299 | else if (usb_guid_cmp(guid, &uvideo_guid_format_nv12) == 0) |
1284 | pixel_format = VIDEO_FORMAT_NV12; | | 1300 | pixel_format = VIDEO_FORMAT_NV12; |
1285 | else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0) | | 1301 | else if (usb_guid_cmp(guid, &uvideo_guid_format_uyvy) == 0) |
1286 | pixel_format = VIDEO_FORMAT_UYVY; | | 1302 | pixel_format = VIDEO_FORMAT_UYVY; |
| | | 1303 | else { |
| | | 1304 | #ifdef UVIDEO_DEBUG |
| | | 1305 | DPRINTF(("%s: unknown format: ", __func__)); |
| | | 1306 | usb_guid_print(guid); |
| | | 1307 | DPRINTF(("\n")); |
| | | 1308 | #endif |
| | | 1309 | } |
1287 | break; | | 1310 | break; |
1288 | case UDESC_VS_FORMAT_FRAME_BASED: | | 1311 | case UDESC_VS_FORMAT_FRAME_BASED: |
| | | 1312 | DPRINTF(("%s: frame-based\n", __func__)); |
1289 | subtype = UDESC_VS_FRAME_FRAME_BASED; | | 1313 | subtype = UDESC_VS_FRAME_FRAME_BASED; |
1290 | default_index = GET(uvideo_format_frame_based_descriptor_t, | | 1314 | default_index = GET(uvideo_format_frame_based_descriptor_t, |
1291 | format_desc, | | 1315 | format_desc, |
1292 | bDefaultFrameIndex); | | 1316 | bDefaultFrameIndex); |
1293 | break; | | 1317 | break; |
1294 | case UDESC_VS_FORMAT_MJPEG: | | 1318 | case UDESC_VS_FORMAT_MJPEG: |
| | | 1319 | DPRINTF(("%s: mjpeg\n", __func__)); |
1295 | subtype = UDESC_VS_FRAME_MJPEG; | | 1320 | subtype = UDESC_VS_FRAME_MJPEG; |
1296 | default_index = GET(uvideo_vs_format_mjpeg_descriptor_t, | | 1321 | default_index = GET(uvideo_vs_format_mjpeg_descriptor_t, |
1297 | format_desc, | | 1322 | format_desc, |
1298 | bDefaultFrameIndex); | | 1323 | bDefaultFrameIndex); |
1299 | pixel_format = VIDEO_FORMAT_MJPEG; | | 1324 | pixel_format = VIDEO_FORMAT_MJPEG; |
1300 | break; | | 1325 | break; |
1301 | default: | | 1326 | default: |
1302 | DPRINTF(("uvideo: unknown frame based format %d\n", | | 1327 | DPRINTF(("uvideo: unknown frame based format %d\n", |
1303 | format_desc->bDescriptorSubtype)); | | 1328 | format_desc->bDescriptorSubtype)); |
1304 | return USBD_INVAL; | | 1329 | return USBD_INVAL; |
1305 | } | | 1330 | } |
1306 | | | 1331 | |
1307 | pformat = NULL; | | 1332 | pformat = NULL; |