ソースを参照

[usb] Handle CDC union functional descriptors

USB Communications Device Class devices may use a union functional
descriptor to group several interfaces into a function.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9年前
コミット
cf153f60a5
3個のファイルの変更100行の追加3行の削除
  1. 50
    0
      src/drivers/bus/cdc.c
  2. 33
    3
      src/drivers/bus/usb.c
  3. 17
    0
      src/include/ipxe/cdc.h

+ 50
- 0
src/drivers/bus/cdc.c ファイルの表示

1
+/*
2
+ * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3
+ *
4
+ * This program is free software; you can redistribute it and/or
5
+ * modify it under the terms of the GNU General Public License as
6
+ * published by the Free Software Foundation; either version 2 of the
7
+ * License, or (at your option) any later version.
8
+ *
9
+ * This program is distributed in the hope that it will be useful, but
10
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
+ * General Public License for more details.
13
+ *
14
+ * You should have received a copy of the GNU General Public License
15
+ * along with this program; if not, write to the Free Software
16
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
+ * 02110-1301, USA.
18
+ */
19
+
20
+FILE_LICENCE ( GPL2_OR_LATER );
21
+
22
+#include <stddef.h>
23
+#include <ipxe/usb.h>
24
+#include <ipxe/cdc.h>
25
+
26
+/** @file
27
+ *
28
+ * USB Communications Device Class (CDC)
29
+ *
30
+ */
31
+
32
+/**
33
+ * Locate CDC union functional descriptor
34
+ *
35
+ * @v config		Configuration descriptor
36
+ * @v interface		Interface descriptor
37
+ * @ret desc		Union functional descriptor, or NULL if not found
38
+ */
39
+struct cdc_union_descriptor *
40
+cdc_union_descriptor ( struct usb_configuration_descriptor *config,
41
+		       struct usb_interface_descriptor *interface ) {
42
+	struct cdc_union_descriptor *desc;
43
+
44
+	for_each_interface_descriptor ( desc, config, interface ) {
45
+		if ( ( desc->header.type == USB_CS_INTERFACE_DESCRIPTOR ) &&
46
+		     ( desc->subtype == CDC_SUBTYPE_UNION ) )
47
+			return desc;
48
+	}
49
+	return NULL;
50
+}

+ 33
- 3
src/drivers/bus/usb.c ファイルの表示

27
 #include <assert.h>
27
 #include <assert.h>
28
 #include <byteswap.h>
28
 #include <byteswap.h>
29
 #include <ipxe/usb.h>
29
 #include <ipxe/usb.h>
30
+#include <ipxe/cdc.h>
30
 
31
 
31
 /** @file
32
 /** @file
32
  *
33
  *
678
 	struct usb_device *usb = func->usb;
679
 	struct usb_device *usb = func->usb;
679
 	struct usb_interface_association_descriptor *association;
680
 	struct usb_interface_association_descriptor *association;
680
 	struct usb_interface_descriptor *interface;
681
 	struct usb_interface_descriptor *interface;
682
+	struct cdc_union_descriptor *cdc_union;
681
 	unsigned int i;
683
 	unsigned int i;
682
 
684
 
683
 	/* First, look for an interface association descriptor */
685
 	/* First, look for an interface association descriptor */
685
 	if ( association ) {
687
 	if ( association ) {
686
 
688
 
687
 		/* Sanity check */
689
 		/* Sanity check */
688
-		if ( ( association->first + association->count ) >
689
-		     config->interfaces ) {
690
+		if ( association->count > config->interfaces ) {
690
 			DBGC ( usb, "USB %s has invalid association [%d-%d)\n",
691
 			DBGC ( usb, "USB %s has invalid association [%d-%d)\n",
691
 			       func->name, association->first,
692
 			       func->name, association->first,
692
 			       ( association->first + association->count ) );
693
 			       ( association->first + association->count ) );
714
 	memcpy ( &func->class, &interface->class, sizeof ( func->class ) );
715
 	memcpy ( &func->class, &interface->class, sizeof ( func->class ) );
715
 	func->count = 1;
716
 	func->count = 1;
716
 	func->interface[0] = first;
717
 	func->interface[0] = first;
718
+
719
+	/* Look for a CDC union descriptor, if applicable */
720
+	if ( ( func->class.class == USB_CLASS_CDC ) &&
721
+	     ( cdc_union = cdc_union_descriptor ( config, interface ) ) ) {
722
+
723
+		/* Determine interface count */
724
+		func->count = ( ( cdc_union->header.len -
725
+				  offsetof ( typeof ( *cdc_union ),
726
+					     interface[0] ) ) /
727
+				sizeof ( cdc_union->interface[0] ) );
728
+		if ( func->count > config->interfaces ) {
729
+			DBGC ( usb, "USB %s has invalid union functional "
730
+			       "descriptor with %d interfaces\n",
731
+			       func->name, func->count );
732
+			return -ERANGE;
733
+		}
734
+
735
+		/* Describe function */
736
+		for ( i = 0 ; i < func->count ; i++ )
737
+			func->interface[i] = cdc_union->interface[i];
738
+
739
+		return 0;
740
+	}
741
+
717
 	return 0;
742
 	return 0;
718
 }
743
 }
719
 
744
 
842
 
867
 
843
 		/* Mark interfaces as used */
868
 		/* Mark interfaces as used */
844
 		for ( i = 0 ; i < func->count ; i++ ) {
869
 		for ( i = 0 ; i < func->count ; i++ ) {
845
-			assert ( func->interface[i] < config->interfaces );
870
+			if ( func->interface[i] >= config->interfaces ) {
871
+				DBGC ( usb, "USB %s has invalid interface %d\n",
872
+				       func->name, func->interface[i] );
873
+				goto err_interface;
874
+			}
846
 			used[ func->interface[i] ] = 1;
875
 			used[ func->interface[i] ] = 1;
847
 		}
876
 		}
848
 
877
 
872
 	err_probe:
901
 	err_probe:
873
 		free ( func );
902
 		free ( func );
874
 	err_alloc:
903
 	err_alloc:
904
+	err_interface:
875
 	err_function:
905
 	err_function:
876
 		/* Continue registering other functions */
906
 		/* Continue registering other functions */
877
 		continue;
907
 		continue;

+ 17
- 0
src/include/ipxe/cdc.h ファイルの表示

14
 /** Class code for communications devices */
14
 /** Class code for communications devices */
15
 #define USB_CLASS_CDC 2
15
 #define USB_CLASS_CDC 2
16
 
16
 
17
+/** Union functional descriptor */
18
+struct cdc_union_descriptor {
19
+	/** Descriptor header */
20
+	struct usb_descriptor_header header;
21
+	/** Descriptor subtype */
22
+	uint8_t subtype;
23
+	/** Interfaces (variable-length) */
24
+	uint8_t interface[1];
25
+} __attribute__ (( packed ));
26
+
27
+/** Union functional descriptor subtype */
28
+#define CDC_SUBTYPE_UNION 6
29
+
17
 /** Ethernet descriptor subtype */
30
 /** Ethernet descriptor subtype */
18
 #define CDC_SUBTYPE_ETHERNET 15
31
 #define CDC_SUBTYPE_ETHERNET 15
19
 
32
 
35
 	uint32_t up;
48
 	uint32_t up;
36
 } __attribute__ (( packed ));
49
 } __attribute__ (( packed ));
37
 
50
 
51
+extern struct cdc_union_descriptor *
52
+cdc_union_descriptor ( struct usb_configuration_descriptor *config,
53
+		       struct usb_interface_descriptor *interface );
54
+
38
 #endif /* _IPXE_CDC_H */
55
 #endif /* _IPXE_CDC_H */

読み込み中…
キャンセル
保存