- Add usb_fill_bulk_urb() and usb_bulk_msg() linux compat functions [1]
- Don't write actual length if the actual length pointer is NULL [2] - correct Linux Compatibility error codes for short isochronous IN transfers and make status field signed. Submitted by: Leunam Elebek [1], Manuel Gebele [2]
This commit is contained in:
parent
bb9c7a8b22
commit
0f92028501
@ -624,10 +624,11 @@ usb_start_wait_urb(struct urb *urb, usb_timeout_t timeout, uint16_t *p_actlen)
|
||||
done:
|
||||
if (do_unlock)
|
||||
mtx_unlock(&Giant);
|
||||
if (err) {
|
||||
*p_actlen = 0;
|
||||
} else {
|
||||
*p_actlen = urb->actual_length;
|
||||
if (p_actlen != NULL) {
|
||||
if (err)
|
||||
*p_actlen = 0;
|
||||
else
|
||||
*p_actlen = urb->actual_length;
|
||||
}
|
||||
return (err);
|
||||
}
|
||||
@ -1362,8 +1363,17 @@ usb_linux_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
for (x = 0; x < urb->number_of_packets; x++) {
|
||||
uipd = urb->iso_frame_desc + x;
|
||||
if (uipd->length > xfer->frlengths[x]) {
|
||||
if (urb->transfer_flags & URB_SHORT_NOT_OK) {
|
||||
/* XXX should be EREMOTEIO */
|
||||
uipd->status = -EPIPE;
|
||||
} else {
|
||||
uipd->status = 0;
|
||||
}
|
||||
} else {
|
||||
uipd->status = 0;
|
||||
}
|
||||
uipd->actual_length = xfer->frlengths[x];
|
||||
uipd->status = 0;
|
||||
if (!xfer->flags.ext_buffer) {
|
||||
usbd_copy_out(xfer->frbuffers, offset,
|
||||
USB_ADD_BYTES(urb->transfer_buffer,
|
||||
@ -1385,8 +1395,8 @@ usb_linux_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
if (xfer->actlen < xfer->sumlen) {
|
||||
/* short transfer */
|
||||
if (urb->transfer_flags & URB_SHORT_NOT_OK) {
|
||||
urb->status = -EPIPE; /* XXX should be
|
||||
* EREMOTEIO */
|
||||
/* XXX should be EREMOTEIO */
|
||||
urb->status = -EPIPE;
|
||||
} else {
|
||||
urb->status = 0;
|
||||
}
|
||||
@ -1482,6 +1492,7 @@ usb_linux_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
/* Set zero for "actual_length" */
|
||||
for (x = 0; x < urb->number_of_packets; x++) {
|
||||
urb->iso_frame_desc[x].actual_length = 0;
|
||||
urb->iso_frame_desc[x].status = urb->status;
|
||||
}
|
||||
|
||||
/* call callback */
|
||||
@ -1663,3 +1674,58 @@ usb_linux_non_isoc_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
goto tr_setup;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_fill_bulk_urb
|
||||
*------------------------------------------------------------------------*/
|
||||
void
|
||||
usb_fill_bulk_urb(struct urb *urb, struct usb_device *udev,
|
||||
struct usb_host_endpoint *uhe, void *buf,
|
||||
int length, usb_complete_t callback, void *arg)
|
||||
{
|
||||
urb->dev = udev;
|
||||
urb->endpoint = uhe;
|
||||
urb->transfer_buffer = buf;
|
||||
urb->transfer_buffer_length = length;
|
||||
urb->complete = callback;
|
||||
urb->context = arg;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*
|
||||
* usb_bulk_msg
|
||||
*
|
||||
* NOTE: This function can also be used for interrupt endpoints!
|
||||
*
|
||||
* Return values:
|
||||
* 0: Success
|
||||
* Else: Failure
|
||||
*------------------------------------------------------------------------*/
|
||||
int
|
||||
usb_bulk_msg(struct usb_device *udev, struct usb_host_endpoint *uhe,
|
||||
void *data, int len, uint16_t *pactlen, usb_timeout_t timeout)
|
||||
{
|
||||
struct urb *urb;
|
||||
int err;
|
||||
|
||||
if (uhe == NULL)
|
||||
return (-EINVAL);
|
||||
if (len < 0)
|
||||
return (-EINVAL);
|
||||
|
||||
err = usb_setup_endpoint(udev, uhe, 4096 /* bytes */);
|
||||
if (err)
|
||||
return (err);
|
||||
|
||||
urb = usb_alloc_urb(0, 0);
|
||||
if (urb == NULL)
|
||||
return (-ENOMEM);
|
||||
|
||||
usb_fill_bulk_urb(urb, udev, uhe, data, len,
|
||||
usb_linux_wait_complete, NULL);
|
||||
|
||||
err = usb_start_wait_urb(urb, timeout, pactlen);
|
||||
|
||||
usb_free_urb(urb);
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ struct usb_iso_packet_descriptor {
|
||||
* packets are usually back to back) */
|
||||
uint16_t length; /* expected length */
|
||||
uint16_t actual_length;
|
||||
uint16_t status;
|
||||
int16_t status; /* transfer status */
|
||||
};
|
||||
|
||||
/*
|
||||
@ -299,6 +299,11 @@ void usb_set_intfdata(struct usb_interface *intf, void *data);
|
||||
void usb_linux_register(void *arg);
|
||||
void usb_linux_deregister(void *arg);
|
||||
|
||||
void usb_fill_bulk_urb(struct urb *, struct usb_device *,
|
||||
struct usb_host_endpoint *, void *, int, usb_complete_t, void *);
|
||||
int usb_bulk_msg(struct usb_device *, struct usb_host_endpoint *,
|
||||
void *, int, uint16_t *, usb_timeout_t);
|
||||
|
||||
#define interface_to_usbdev(intf) (intf)->linux_udev
|
||||
#define interface_to_bsddev(intf) (intf)->linux_udev
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user