Browse Source

usb: generalize the ACM descriptor set; handle > 256 byte desc ROM

Move the ACM descriptor set generation into a subroutine, so it can
generate an arbitrary number of interfaces. This is verified to work.

Handle a USB descriptor ROM larger than 256 bytes, as needed for more
than 1 ACM channel.
H. Peter Anvin 3 years ago
parent
commit
492d654ec1

BIN
fpga/output_files/max80.jic


BIN
fpga/output_files/max80.pof


+ 43 - 27
fpga/usb/usb_desc.conf

@@ -9,31 +9,21 @@ my $vendor_id    = word(0x1d50);
 my $device_id    = word(0x6149);
 my $version_id   = word(0x0100);
 
-my $serial       = usb_serial('Cereal');
+my $serial       = usb_serial('_serial_here_');
 my $manufacturer = usb_string(''   => 'Peter & Per');
 my $product      = usb_string(''   => 'MAX80 I/O card for ABC');
 
-my $mgmt_if, $data_if;
+sub acm_channels($$) {
+    my($channel_count,$ep_base) = @_;
+    my @d;
 
-usb_device {
-    usb_desc('device',
-	     word(0x101),		# USB version
-	     usb_class('multi'),	# Device with multiple interfaces
-	     byte(8),			# Max packet size on endpoint 0
-	     $vendor_id, $device_id, $version_id,
-	     $manufacturer, $product, $serial,
-	     byte(usb_children)		# Number of configurations
-	),
+    for (my $c = 0; $c < $channel_count; $c++) {
+	my $ep_data = $ep_base + ($c << 1);
+	my $ep_intr = $ep_data + 1;
 
-	usb_dset {
-	    usb_desc('configuration',
-		     word(usb_totallen), # Total length for this dset
-		     byte(usb_children), # Number of interfaces
-		     byte(usb_index,1),	 # This configuration index
-		     usb_string(),	 # Text description (empty)
-		     byte(0xc0),	 # Self or bus powered
-		     byte(500 >> 1)),	 # Up to 500 mA
+	my $mgmt_if, $data_if;
 
+	push(@d,
 		# Interface association descriptor
 		usb_desc('interface_association',
 			 byte(\$mgmt_if), # First interface index
@@ -41,7 +31,7 @@ usb_device {
 			 # USB spec says to copy the first interface class
 			 usb_class('cdc','acm','v25ter'),
 			 usb_string()),
-		
+
 		# Management interface
 		usb_dset {
 		    usb_desc('interface',
@@ -65,9 +55,9 @@ usb_device {
 				 byte(\$mgmt_if),	# Controlling interface
 				 byte(\$data_if)),	# Data interface
 
-			# EP 3, input: notification
+			# Notification endpoint (input)
 			usb_desc('endpoint',
-				 ep_i(3),	# Endpoint 3 input
+				 ep_i($ep_intr),
 				 byte(3),	# Interrupt, data
 				 word(64),	# Max packet size
 				 byte(2)),	# Interval
@@ -82,21 +72,47 @@ usb_device {
 			     usb_class('cdc_data'),
 			     usb_string()),
 
-			# EP 2, input: upstream data
+			# Data endpoint (input)
 			usb_desc('endpoint',
-				 ep_i(2),
+				 ep_i($ep_data),
 				 byte(2),      # Bulk, data
 				 word(64),     # Max packet size
 				 byte(0)),     # Interval
 
-			# EP 2, output: downstream data
+			# Data endpoint (output)
 			usb_desc('endpoint',
-				 ep_o(2),
+				 ep_o($ep_data),
 				 byte(2),	# Bulk, data
 				 word(64),	# Max packet size
 				 byte(0))       # Interval
 
-	    }
+	     });
+    }
+
+    return @d;
+}
+
+usb_device {
+    usb_desc('device',
+	     word(0x101),		# USB version
+	     usb_class('multi'),	# Device with multiple interfaces
+	     byte(8),			# Max packet size on endpoint 0
+	     $vendor_id, $device_id, $version_id,
+	     $manufacturer, $product, $serial,
+	     byte(usb_children)		# Number of configurations
+	),
+
+	usb_dset {
+	    usb_desc('configuration',
+		     word(usb_totallen), # Total length for this dset
+		     byte(usb_children), # Number of interfaces
+		     byte(usb_index,1),	 # This configuration index
+		     usb_string(),	 # Text description (empty)
+		     byte(0xc0),	 # Self or bus powered
+		     byte(500 >> 1)),	 # Up to 500 mA
+
+		# Descriptors for each ACM channel
+		acm_channels(1,2)	# 1 channel starting at EP 2
     },
 };
 

+ 170 - 156
fpga/usb/usb_desc.v

@@ -17,198 +17,212 @@ module usb_desc_rom (
 	reg [7:0] rom [0:255];
 
 	initial begin
-		rom[8'h00] = 8'h0e;
+		rom[8'h00] = 8'h1c;
 		rom[8'h01] = 8'h03;
-		rom[8'h02] = 8'h43;
+		rom[8'h02] = 8'h5f;
 		rom[8'h03] = 8'h00;
-		rom[8'h04] = 8'h65;
+		rom[8'h04] = 8'h73;
 		rom[8'h05] = 8'h00;
-		rom[8'h06] = 8'h72;
+		rom[8'h06] = 8'h65;
 		rom[8'h07] = 8'h00;
-		rom[8'h08] = 8'h65;
+		rom[8'h08] = 8'h72;
 		rom[8'h09] = 8'h00;
-		rom[8'h0a] = 8'h61;
+		rom[8'h0a] = 8'h69;
 		rom[8'h0b] = 8'h00;
-		rom[8'h0c] = 8'h6c;
+		rom[8'h0c] = 8'h61;
 		rom[8'h0d] = 8'h00;
-		rom[8'h0e] = 8'h12;
-		rom[8'h0f] = 8'h01;
-		rom[8'h10] = 8'h01;
-		rom[8'h11] = 8'h01;
-		rom[8'h12] = 8'h00;
+		rom[8'h0e] = 8'h6c;
+		rom[8'h0f] = 8'h00;
+		rom[8'h10] = 8'h5f;
+		rom[8'h11] = 8'h00;
+		rom[8'h12] = 8'h68;
 		rom[8'h13] = 8'h00;
-		rom[8'h14] = 8'h00;
-		rom[8'h15] = 8'h08;
-		rom[8'h16] = 8'h50;
-		rom[8'h17] = 8'h1d;
-		rom[8'h18] = 8'h49;
-		rom[8'h19] = 8'h61;
-		rom[8'h1a] = 8'h00;
-		rom[8'h1b] = 8'h01;
-		rom[8'h1c] = 8'h02;
-		rom[8'h1d] = 8'h03;
+		rom[8'h14] = 8'h65;
+		rom[8'h15] = 8'h00;
+		rom[8'h16] = 8'h72;
+		rom[8'h17] = 8'h00;
+		rom[8'h18] = 8'h65;
+		rom[8'h19] = 8'h00;
+		rom[8'h1a] = 8'h5f;
+		rom[8'h1b] = 8'h00;
+		rom[8'h1c] = 8'h12;
+		rom[8'h1d] = 8'h01;
 		rom[8'h1e] = 8'h01;
 		rom[8'h1f] = 8'h01;
-		rom[8'h20] = 8'h09;
-		rom[8'h21] = 8'h02;
-		rom[8'h22] = 8'h4b;
-		rom[8'h23] = 8'h00;
-		rom[8'h24] = 8'h02;
-		rom[8'h25] = 8'h01;
-		rom[8'h26] = 8'h04;
-		rom[8'h27] = 8'hc0;
-		rom[8'h28] = 8'hfa;
-		rom[8'h29] = 8'h08;
-		rom[8'h2a] = 8'h0b;
-		rom[8'h2b] = 8'h00;
-		rom[8'h2c] = 8'h02;
-		rom[8'h2d] = 8'h02;
-		rom[8'h2e] = 8'h02;
-		rom[8'h2f] = 8'h01;
-		rom[8'h30] = 8'h04;
-		rom[8'h31] = 8'h09;
-		rom[8'h32] = 8'h04;
-		rom[8'h33] = 8'h00;
-		rom[8'h34] = 8'h00;
-		rom[8'h35] = 8'h01;
-		rom[8'h36] = 8'h02;
-		rom[8'h37] = 8'h02;
-		rom[8'h38] = 8'h01;
-		rom[8'h39] = 8'h04;
-		rom[8'h3a] = 8'h05;
-		rom[8'h3b] = 8'h24;
-		rom[8'h3c] = 8'h00;
-		rom[8'h3d] = 8'h20;
-		rom[8'h3e] = 8'h01;
-		rom[8'h3f] = 8'h05;
-		rom[8'h40] = 8'h24;
-		rom[8'h41] = 8'h01;
-		rom[8'h42] = 8'h03;
+		rom[8'h20] = 8'h00;
+		rom[8'h21] = 8'h00;
+		rom[8'h22] = 8'h00;
+		rom[8'h23] = 8'h08;
+		rom[8'h24] = 8'h50;
+		rom[8'h25] = 8'h1d;
+		rom[8'h26] = 8'h49;
+		rom[8'h27] = 8'h61;
+		rom[8'h28] = 8'h00;
+		rom[8'h29] = 8'h01;
+		rom[8'h2a] = 8'h02;
+		rom[8'h2b] = 8'h03;
+		rom[8'h2c] = 8'h01;
+		rom[8'h2d] = 8'h01;
+		rom[8'h2e] = 8'h09;
+		rom[8'h2f] = 8'h02;
+		rom[8'h30] = 8'h4b;
+		rom[8'h31] = 8'h00;
+		rom[8'h32] = 8'h02;
+		rom[8'h33] = 8'h01;
+		rom[8'h34] = 8'h04;
+		rom[8'h35] = 8'hc0;
+		rom[8'h36] = 8'hfa;
+		rom[8'h37] = 8'h08;
+		rom[8'h38] = 8'h0b;
+		rom[8'h39] = 8'h00;
+		rom[8'h3a] = 8'h02;
+		rom[8'h3b] = 8'h02;
+		rom[8'h3c] = 8'h02;
+		rom[8'h3d] = 8'h01;
+		rom[8'h3e] = 8'h04;
+		rom[8'h3f] = 8'h09;
+		rom[8'h40] = 8'h04;
+		rom[8'h41] = 8'h00;
+		rom[8'h42] = 8'h00;
 		rom[8'h43] = 8'h01;
-		rom[8'h44] = 8'h04;
-		rom[8'h45] = 8'h24;
-		rom[8'h46] = 8'h02;
+		rom[8'h44] = 8'h02;
+		rom[8'h45] = 8'h02;
+		rom[8'h46] = 8'h01;
 		rom[8'h47] = 8'h04;
 		rom[8'h48] = 8'h05;
 		rom[8'h49] = 8'h24;
-		rom[8'h4a] = 8'h06;
-		rom[8'h4b] = 8'h00;
+		rom[8'h4a] = 8'h00;
+		rom[8'h4b] = 8'h20;
 		rom[8'h4c] = 8'h01;
-		rom[8'h4d] = 8'h07;
-		rom[8'h4e] = 8'h05;
-		rom[8'h4f] = 8'h83;
+		rom[8'h4d] = 8'h05;
+		rom[8'h4e] = 8'h24;
+		rom[8'h4f] = 8'h01;
 		rom[8'h50] = 8'h03;
-		rom[8'h51] = 8'h40;
-		rom[8'h52] = 8'h00;
-		rom[8'h53] = 8'h02;
-		rom[8'h54] = 8'h09;
+		rom[8'h51] = 8'h01;
+		rom[8'h52] = 8'h04;
+		rom[8'h53] = 8'h24;
+		rom[8'h54] = 8'h02;
 		rom[8'h55] = 8'h04;
-		rom[8'h56] = 8'h01;
-		rom[8'h57] = 8'h00;
-		rom[8'h58] = 8'h02;
-		rom[8'h59] = 8'h0a;
-		rom[8'h5a] = 8'h00;
-		rom[8'h5b] = 8'h00;
-		rom[8'h5c] = 8'h04;
-		rom[8'h5d] = 8'h07;
-		rom[8'h5e] = 8'h05;
-		rom[8'h5f] = 8'h82;
-		rom[8'h60] = 8'h02;
-		rom[8'h61] = 8'h40;
-		rom[8'h62] = 8'h00;
-		rom[8'h63] = 8'h00;
-		rom[8'h64] = 8'h07;
-		rom[8'h65] = 8'h05;
+		rom[8'h56] = 8'h05;
+		rom[8'h57] = 8'h24;
+		rom[8'h58] = 8'h06;
+		rom[8'h59] = 8'h00;
+		rom[8'h5a] = 8'h01;
+		rom[8'h5b] = 8'h07;
+		rom[8'h5c] = 8'h05;
+		rom[8'h5d] = 8'h83;
+		rom[8'h5e] = 8'h03;
+		rom[8'h5f] = 8'h40;
+		rom[8'h60] = 8'h00;
+		rom[8'h61] = 8'h02;
+		rom[8'h62] = 8'h09;
+		rom[8'h63] = 8'h04;
+		rom[8'h64] = 8'h01;
+		rom[8'h65] = 8'h00;
 		rom[8'h66] = 8'h02;
-		rom[8'h67] = 8'h02;
-		rom[8'h68] = 8'h40;
+		rom[8'h67] = 8'h0a;
+		rom[8'h68] = 8'h00;
 		rom[8'h69] = 8'h00;
-		rom[8'h6a] = 8'h00;
-		rom[8'h6b] = 8'h06;
-		rom[8'h6c] = 8'h03;
-		rom[8'h6d] = 8'h09;
-		rom[8'h6e] = 8'h04;
-		rom[8'h6f] = 8'h1d;
-		rom[8'h70] = 8'h04;
-		rom[8'h71] = 8'h18;
-		rom[8'h72] = 8'h03;
-		rom[8'h73] = 8'h50;
-		rom[8'h74] = 8'h00;
-		rom[8'h75] = 8'h65;
-		rom[8'h76] = 8'h00;
-		rom[8'h77] = 8'h74;
+		rom[8'h6a] = 8'h04;
+		rom[8'h6b] = 8'h07;
+		rom[8'h6c] = 8'h05;
+		rom[8'h6d] = 8'h82;
+		rom[8'h6e] = 8'h02;
+		rom[8'h6f] = 8'h40;
+		rom[8'h70] = 8'h00;
+		rom[8'h71] = 8'h00;
+		rom[8'h72] = 8'h07;
+		rom[8'h73] = 8'h05;
+		rom[8'h74] = 8'h02;
+		rom[8'h75] = 8'h02;
+		rom[8'h76] = 8'h40;
+		rom[8'h77] = 8'h00;
 		rom[8'h78] = 8'h00;
-		rom[8'h79] = 8'h65;
-		rom[8'h7a] = 8'h00;
-		rom[8'h7b] = 8'h72;
-		rom[8'h7c] = 8'h00;
-		rom[8'h7d] = 8'h20;
-		rom[8'h7e] = 8'h00;
-		rom[8'h7f] = 8'h26;
-		rom[8'h80] = 8'h00;
-		rom[8'h81] = 8'h20;
+		rom[8'h79] = 8'h06;
+		rom[8'h7a] = 8'h03;
+		rom[8'h7b] = 8'h09;
+		rom[8'h7c] = 8'h04;
+		rom[8'h7d] = 8'h1d;
+		rom[8'h7e] = 8'h04;
+		rom[8'h7f] = 8'h18;
+		rom[8'h80] = 8'h03;
+		rom[8'h81] = 8'h50;
 		rom[8'h82] = 8'h00;
-		rom[8'h83] = 8'h50;
+		rom[8'h83] = 8'h65;
 		rom[8'h84] = 8'h00;
-		rom[8'h85] = 8'h65;
+		rom[8'h85] = 8'h74;
 		rom[8'h86] = 8'h00;
-		rom[8'h87] = 8'h72;
+		rom[8'h87] = 8'h65;
 		rom[8'h88] = 8'h00;
-		rom[8'h89] = 8'h2e;
-		rom[8'h8a] = 8'h03;
-		rom[8'h8b] = 8'h4d;
+		rom[8'h89] = 8'h72;
+		rom[8'h8a] = 8'h00;
+		rom[8'h8b] = 8'h20;
 		rom[8'h8c] = 8'h00;
-		rom[8'h8d] = 8'h41;
+		rom[8'h8d] = 8'h26;
 		rom[8'h8e] = 8'h00;
-		rom[8'h8f] = 8'h58;
+		rom[8'h8f] = 8'h20;
 		rom[8'h90] = 8'h00;
-		rom[8'h91] = 8'h38;
+		rom[8'h91] = 8'h50;
 		rom[8'h92] = 8'h00;
-		rom[8'h93] = 8'h30;
+		rom[8'h93] = 8'h65;
 		rom[8'h94] = 8'h00;
-		rom[8'h95] = 8'h20;
+		rom[8'h95] = 8'h72;
 		rom[8'h96] = 8'h00;
-		rom[8'h97] = 8'h49;
-		rom[8'h98] = 8'h00;
-		rom[8'h99] = 8'h2f;
+		rom[8'h97] = 8'h2e;
+		rom[8'h98] = 8'h03;
+		rom[8'h99] = 8'h4d;
 		rom[8'h9a] = 8'h00;
-		rom[8'h9b] = 8'h4f;
+		rom[8'h9b] = 8'h41;
 		rom[8'h9c] = 8'h00;
-		rom[8'h9d] = 8'h20;
+		rom[8'h9d] = 8'h58;
 		rom[8'h9e] = 8'h00;
-		rom[8'h9f] = 8'h63;
+		rom[8'h9f] = 8'h38;
 		rom[8'ha0] = 8'h00;
-		rom[8'ha1] = 8'h61;
+		rom[8'ha1] = 8'h30;
 		rom[8'ha2] = 8'h00;
-		rom[8'ha3] = 8'h72;
+		rom[8'ha3] = 8'h20;
 		rom[8'ha4] = 8'h00;
-		rom[8'ha5] = 8'h64;
+		rom[8'ha5] = 8'h49;
 		rom[8'ha6] = 8'h00;
-		rom[8'ha7] = 8'h20;
+		rom[8'ha7] = 8'h2f;
 		rom[8'ha8] = 8'h00;
-		rom[8'ha9] = 8'h66;
+		rom[8'ha9] = 8'h4f;
 		rom[8'haa] = 8'h00;
-		rom[8'hab] = 8'h6f;
+		rom[8'hab] = 8'h20;
 		rom[8'hac] = 8'h00;
-		rom[8'had] = 8'h72;
+		rom[8'had] = 8'h63;
 		rom[8'hae] = 8'h00;
-		rom[8'haf] = 8'h20;
+		rom[8'haf] = 8'h61;
 		rom[8'hb0] = 8'h00;
-		rom[8'hb1] = 8'h41;
+		rom[8'hb1] = 8'h72;
 		rom[8'hb2] = 8'h00;
-		rom[8'hb3] = 8'h42;
+		rom[8'hb3] = 8'h64;
 		rom[8'hb4] = 8'h00;
-		rom[8'hb5] = 8'h43;
+		rom[8'hb5] = 8'h20;
 		rom[8'hb6] = 8'h00;
-		rom[8'hb7] = 8'h02;
-		rom[8'hb8] = 8'h03;
-		rom[8'hb9] = 8'h00;
-		rom[8'hba] = 8'hc2;
-		rom[8'hbb] = 8'h01;
+		rom[8'hb7] = 8'h66;
+		rom[8'hb8] = 8'h00;
+		rom[8'hb9] = 8'h6f;
+		rom[8'hba] = 8'h00;
+		rom[8'hbb] = 8'h72;
 		rom[8'hbc] = 8'h00;
-		rom[8'hbd] = 8'h00;
+		rom[8'hbd] = 8'h20;
 		rom[8'hbe] = 8'h00;
-		rom[8'hbf] = 8'h08;
+		rom[8'hbf] = 8'h41;
+		rom[8'hc0] = 8'h00;
+		rom[8'hc1] = 8'h42;
+		rom[8'hc2] = 8'h00;
+		rom[8'hc3] = 8'h43;
+		rom[8'hc4] = 8'h00;
+		rom[8'hc5] = 8'h02;
+		rom[8'hc6] = 8'h03;
+		rom[8'hc7] = 8'h00;
+		rom[8'hc8] = 8'hc2;
+		rom[8'hc9] = 8'h01;
+		rom[8'hca] = 8'h00;
+		rom[8'hcb] = 8'h00;
+		rom[8'hcc] = 8'h00;
+		rom[8'hcd] = 8'h08;
 	end
 
 	always @(posedge clk) begin
@@ -231,18 +245,18 @@ module usb_desc_index (
 
 	always @(*)
        	if (additional)
-		{addr,len} = {8'hb9,8'h07};
+		{addr,len} = {8'hc7,8'h07};
 	else priority casez ({windex,dindex,dtype})
-		32'b??????00_00011101_00000010_00000011: {addr,len} = {8'h71,8'h18};
-		32'b??????00_00011101_00000011_00000011: {addr,len} = {8'h89,8'h2e};
-		32'b??????00_00011101_00000100_00000011: {addr,len} = {8'hb7,8'h02};
-		32'b????????_????????_00000000_00000010: {addr,len} = {8'h20,8'h4b};
-		32'b????????_????????_00000000_00000011: {addr,len} = {8'h6b,8'h06};
-		32'b????????_????????_00000001_00000011: {addr,len} = {8'h00,8'h0e};
-		32'b????????_????????_00000010_00000011: {addr,len} = {8'h71,8'h18};
-		32'b????????_????????_00000011_00000011: {addr,len} = {8'h89,8'h2e};
-		32'b????????_????????_00000100_00000011: {addr,len} = {8'hb7,8'h02};
-		32'b????????_????????_????????_00000001: {addr,len} = {8'h0e,8'h12};
+		32'b??????00_00011101_00000010_00000011: {addr,len} = {8'h7f,8'h18};
+		32'b??????00_00011101_00000011_00000011: {addr,len} = {8'h97,8'h2e};
+		32'b??????00_00011101_00000100_00000011: {addr,len} = {8'hc5,8'h02};
+		32'b????????_????????_00000000_00000010: {addr,len} = {8'h2e,8'h4b};
+		32'b????????_????????_00000000_00000011: {addr,len} = {8'h79,8'h06};
+		32'b????????_????????_00000001_00000011: {addr,len} = {8'h00,8'h1c};
+		32'b????????_????????_00000010_00000011: {addr,len} = {8'h7f,8'h18};
+		32'b????????_????????_00000011_00000011: {addr,len} = {8'h97,8'h2e};
+		32'b????????_????????_00000100_00000011: {addr,len} = {8'hc5,8'h02};
+		32'b????????_????????_????????_00000001: {addr,len} = {8'h1c,8'h12};
 		32'b????????_????????_????????_????????: {addr,len} = {8'hxx,8'h00};
 	endcase
 endmodule

+ 4 - 4
fpga/usb/usb_serial/src_v/usb_cdc_core.sv

@@ -508,8 +508,8 @@ module usb_cdc_core
    reg	       ctrl_ack_r;   // Send STATUS (ZLP)
    reg 	       ctrl_send_data_r;
 
-   reg [7:0]   desc_base_addr_r;
-   reg [7:0]   desc_len_r;
+   reg [15:0]  desc_base_addr_r;
+   reg [15:0]  desc_len_r;
 
    reg	       rx_break_q;
    reg	       rx_break_r;
@@ -709,8 +709,8 @@ module usb_cdc_core
 
    wire       ctrl_send_accept_w = usb_ep[0].u.tx_data_accept || !usb_ep[0].d.tx_data_valid;
 
-   reg  [7:0] desc_addr_r;
-   reg  [7:0] desc_addr_q;
+   reg  [15:0] desc_addr_r;
+   reg  [15:0] desc_addr_q;
    wire [7:0] desc_data_w;
 
    always @ *