On Thursday 17 May 2007 19:44, David Brownell wrote:
> On Thursday 17 May 2007, Hans Petter Selasky wrote:
> > I would like introduce a new USB API call, so that my pre-allocate model
> > will work better with your USB API. For example I want something like
> > this:
> >
> > void
> > usb_setup_endpoint(struct usb_device *usb, struct usb_interface *ui,
> > struct usb_host_endpoint *uhe, uint32_t bufsize, uint32_t unused0,
> > uint32_t unused1, uint32_t unused2);
>
> The usb_device and usb_interface are implied by the usb_host_endpoint,
> and "unused" parameters are pointless. Sizes are "size_t", and such
> a call could obviously fail because of invalid parameters. So
>
> int usb_setup_endpoint(struct usb_host_endpoint *hep, size_t bufsize);
To save the "hep" to "struct usb_device" pointer, I would like to have "struct
usb_device *dev" as an argument.
>
> What would such a call do, though? Who would use it, and why?
The call will setup one or two pre-allocated USB transfers for the emulation
layer between the Linux USB stack and the FreeBSD USB stack.
I've currently put the following into this function:
int32_t
usb_setup_endpoint(struct usb_device *dev, struct usb_host_endpoint *uhe,
uint32_t bufsize)
{
struct usbd_config cfg[2];
uint16_t mfs = usbd_get_max_frame_size((usb_endpoint_descriptor_t
*)&(uhe->desc));
uint8_t type = uhe->desc.bmAttributes & UE_XFERTYPE;
uint8_t addr = uhe->desc.bEndpointAddress;
usbd_transfer_unsetup(uhe->bsd_xfer, 2);
if (bufsize == 0) {
return 0;
}
bzero(cfg, sizeof(cfg));
if (type == UE_ISOCHRONOUS) {
/* Isochronous is special */
cfg[0].type = type;
cfg[0].endpoint = addr & UE_ADDR;
cfg[0].direction = addr & (UE_DIR_OUT|UE_DIR_IN);
cfg[0].callback = &usb_linux_isoc_callback;
cfg[0].bufsize = 0; /* use wMaxPacketSize */
bcopy(cfg + 0, cfg + 1, sizeof(*cfg));
if (usbd_transfer_setup(dev->bsd_udev, uhe->bsd_iface_index,
uhe->bsd_xfer, cfg, 2, uhe,
&usb_global_lock))
{
return -EINVAL;
}
} else {
if (bufsize > (1 << 22)) {
/* limit buffer size */
bufsize = (1 << 22);
}
if (type == UE_CONTROL) {
/* we need enough room for the control header */
if (bufsize < sizeof(usb_device_request_t)) {
bufsize = sizeof(usb_device_request_t);
}
}
if (bufsize < mfs) {
/* we need to be able to hold at least one frame! */
bufsize = mfs;
}
cfg[0].type = type;
cfg[0].endpoint = addr & UE_ADDR;
cfg[0].direction = addr & (UE_DIR_OUT|UE_DIR_IN);
cfg[0].callback = &usb_linux_non_isoc_callback;
cfg[0].bufsize = bufsize;
if (usbd_transfer_setup(dev->bsd_udev, uhe->bsd_iface_index,
uhe->bsd_xfer, cfg, 1, uhe,
&usb_global_lock))
{
return -EINVAL;
}
}
return 0;
}
The reason for this is to allow Linux USB drivers to tell the FreeBSD USB
stack that they want larger/smaller buffers.
On Linux this information can be used to reserve EHCI/UHCI/OHCI USB transfer
descriptors.
>
> > On FreeBSD this function will pre-allocate one or two USB transfers for
> > an endpoint using the given "bufsize" argument. Those FreeBSD USB
> > transfers will then be used to do all the Linux USB transfers. This
> > function can block and must have a context.
>
> So what's the model ... GPL'd Linux drivers will be modified to
> incorporate that call, so they'd work better on FreeBSD?
Yes, and under Linux.
As you can see, it is not possible to emulate an on-the-fly allocation model
by a pre-allocation model. That's why I suggest this API addition.
--HPS
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel