|
@@ -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
|
|
|
},
|
|
|
};
|
|
|
|