mirror of
https://github.com/opnsense/src.git
synced 2026-06-10 17:22:46 -04:00
Workaround for USB MIDI adapters which use non-supported values of
wMaxPacketSize for BULK endpoints. MFC after: 1 week
This commit is contained in:
parent
2c2752d351
commit
e91fe3a904
4 changed files with 45 additions and 0 deletions
|
|
@ -5674,6 +5674,25 @@ umidi_probe(device_t dev)
|
|||
DPRINTF("error=%s\n", usbd_errstr(error));
|
||||
goto detach;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some USB MIDI device makers couldn't resist using
|
||||
* wMaxPacketSize = 4 for RX and TX BULK endpoints, although
|
||||
* that size is an unsupported value for FULL speed BULK
|
||||
* endpoints. The same applies to some HIGH speed MIDI devices
|
||||
* which are using a wMaxPacketSize different from 512 bytes.
|
||||
*
|
||||
* Refer to section 5.8.3 in USB 2.0 PDF: Cite: "All Host
|
||||
* Controllers are required to have support for 8-, 16-, 32-,
|
||||
* and 64-byte maximum packet sizes for full-speed bulk
|
||||
* endpoints and 512 bytes for high-speed bulk endpoints."
|
||||
*/
|
||||
if (usbd_xfer_maxp_was_clamped(chan->xfer[UMIDI_TX_TRANSFER]))
|
||||
chan->single_command = 1;
|
||||
|
||||
if (chan->single_command != 0)
|
||||
device_printf(dev, "Single command MIDI quirk enabled\n");
|
||||
|
||||
if ((chan->max_cable > UMIDI_CABLES_MAX) ||
|
||||
(chan->max_cable == 0)) {
|
||||
chan->max_cable = UMIDI_CABLES_MAX;
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ struct usb_xfer_flags_int {
|
|||
uint8_t can_cancel_immed:1; /* set if USB transfer can be
|
||||
* cancelled immediately */
|
||||
uint8_t doing_callback:1; /* set if executing the callback */
|
||||
uint8_t maxp_was_clamped:1; /* set if the max packet size
|
||||
* was outside its allowed range */
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -346,6 +346,7 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
|||
usb_frcount_t n_frlengths;
|
||||
usb_frcount_t n_frbuffers;
|
||||
usb_frcount_t x;
|
||||
uint16_t maxp_old;
|
||||
uint8_t type;
|
||||
uint8_t zmps;
|
||||
|
||||
|
|
@ -433,6 +434,11 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
|||
if (xfer->max_packet_count > parm->hc_max_packet_count) {
|
||||
xfer->max_packet_count = parm->hc_max_packet_count;
|
||||
}
|
||||
|
||||
/* store max packet size value before filtering */
|
||||
|
||||
maxp_old = xfer->max_packet_size;
|
||||
|
||||
/* filter "wMaxPacketSize" according to HC capabilities */
|
||||
|
||||
if ((xfer->max_packet_size > parm->hc_max_packet_size) ||
|
||||
|
|
@ -465,6 +471,13 @@ usbd_transfer_setup_sub(struct usb_setup_params *parm)
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if the max packet size was outside its allowed range
|
||||
* and clamped to a valid value:
|
||||
*/
|
||||
if (maxp_old != xfer->max_packet_size)
|
||||
xfer->flags_int.maxp_was_clamped = 1;
|
||||
|
||||
/* compute "max_frame_size" */
|
||||
|
||||
usbd_update_max_frame_size(xfer);
|
||||
|
|
@ -3432,3 +3445,13 @@ usbd_xfer_get_timestamp(struct usb_xfer *xfer)
|
|||
{
|
||||
return (xfer->isoc_time_complete);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following function returns non-zero if the max packet size
|
||||
* field was clamped to a valid value. Else it returns zero.
|
||||
*/
|
||||
uint8_t
|
||||
usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer)
|
||||
{
|
||||
return (xfer->flags_int.maxp_was_clamped);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -569,6 +569,7 @@ int usbd_xfer_is_stalled(struct usb_xfer *xfer);
|
|||
void usbd_xfer_set_flag(struct usb_xfer *xfer, int flag);
|
||||
void usbd_xfer_clr_flag(struct usb_xfer *xfer, int flag);
|
||||
uint16_t usbd_xfer_get_timestamp(struct usb_xfer *xfer);
|
||||
uint8_t usbd_xfer_maxp_was_clamped(struct usb_xfer *xfer);
|
||||
|
||||
void usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
|
||||
const void *ptr, usb_frlength_t len);
|
||||
|
|
|
|||
Loading…
Reference in a new issue