PERFORCE change 126719 for review
Hans Petter Selasky
hselasky at FreeBSD.org
Sun Sep 23 04:59:48 PDT 2007
http://perforce.freebsd.org/chv.cgi?CH=126719
Change 126719 by hselasky at hselasky_laptop001 on 2007/09/23 11:59:42
FYI; The comments follow the P4 diff from top to bottom.
- change return type of "ugen_allocate_blocks()"
- "ugen_allocate_blocks()" is now called unlocked
- rename "__usbd_transfer_setup()" to "ugen_transfer_setup()"
- "ugen_transfer_setup()" now also allocate buffer memory by
calling "ugen_allocate_blocks()".
- new function "ugen_usb_uiomove()" that transfers memory directly
between an USB transfer and UIO
- rename "__uiomove()" into "ugen_uiomove()".
- updated several "flags |= XXX" to "flags.xxx = 1".
- the maximum frame size must be read from the USB transfer
- all USB BULK/ISOC/INTR IN-transfers must setup
"xfer->frlengths[]" before calling "usbd_start_hardware()".
Else the actual length of the previous transfer will be
used for transfer length of the next USB transfer.
- updated several "flags & XXX" to "flags_int.xxx".
- USB callbacks should return in case of "xfer->error == USBD_CANCELLED".
- "usbreq_set_interface()" has been renamed
"usbd_set_alt_interface_index()" to clearly show that this
function does more than just an USB control request.
- passing a mutex to "usbd_do_request_flags()" and all
"usbreq_xxx()" functions is now mandatory.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/ugen.c#21 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/ugen.c#21 (text+ko) ====
@@ -66,8 +66,6 @@
#define UGEN_HW_FRAMES 50 /* number of milliseconds per transfer */
-#define ADD_BYTES(ptr,size) ((void *)(((u_int8_t *)(ptr)) + (size)))
-
struct ugen_frame_ring {
u_int16_t input_index;
u_int16_t output_index;
@@ -295,7 +293,7 @@
}
else
{
- *ptr = ADD_BYTES
+ *ptr = USBD_ADD_BYTES
(ufr->buf,
ufr->frame_size*ufr->input_index);
@@ -318,7 +316,7 @@
}
else
{
- *ptr = ADD_BYTES
+ *ptr = USBD_ADD_BYTES
(ufr->buf,
ufr->frame_size*ufr->output_index);
@@ -327,21 +325,22 @@
return;
}
-static int
+static usbd_status
ugen_allocate_blocks(struct ugen_softc *sc,
struct ugen_endpoint *sce,
- u_int16_t context_bit,
struct ugen_frame_ring *ufr,
u_int16_t frames,
u_int16_t frame_size)
{
void *ptr;
+ mtx_lock(&(sc->sc_mtx));
bzero(ufr, sizeof(*ufr));
+ mtx_unlock(&(sc->sc_mtx));
if(frames == 0)
{
- return 0;
+ return USBD_INVAL;
}
/* one frame will always be unused
@@ -350,37 +349,21 @@
*/
frames++;
- sce->state |= context_bit;
-
- mtx_unlock(&sc->sc_mtx);
-
ptr = malloc(frames*(frame_size + sizeof(u_int16_t)),
M_USBDEV, M_WAITOK);
- mtx_lock(&sc->sc_mtx);
-
- sce->state &= ~context_bit;
-
- if(sce->state & UGEN_CLOSING)
- {
- wakeup(sce);
- if(ptr)
- {
- free(ptr, M_USBDEV);
- ptr = NULL;
- }
- }
-
if(ptr == NULL)
{
- return 0;
+ return USBD_NOMEM;
}
+ mtx_lock(&(sc->sc_mtx));
ufr->end_index = frames;
ufr->frame_size = frame_size;
- ufr->frlengths = ADD_BYTES(ptr, frames*frame_size);
- ufr->buf = ADD_BYTES(ptr, 0);
- return 1;
+ ufr->frlengths = USBD_ADD_BYTES(ptr, frames*frame_size);
+ ufr->buf = USBD_ADD_BYTES(ptr, 0);
+ mtx_unlock(&(sc->sc_mtx));
+ return 0;
}
static void
@@ -402,12 +385,19 @@
u_int8_t iface_index,
struct usbd_xfer **pxfer,
const struct usbd_config *setup,
- u_int8_t n_setup)
+ u_int8_t n_setup,
+ uint16_t n_in_frames,
+ uint16_t n_out_frames)
{
struct usbd_xfer * temp[n_setup];
usbd_status error;
+ if ((n_out_frames > 0) && (n_in_frames > 0)) {
+ /* should not happen */
+ return USBD_INVAL;
+ }
+
sce->state |= context_bit;
mtx_unlock(&sc->sc_mtx);
@@ -419,7 +409,22 @@
error = usbd_transfer_setup(udev, iface_index, &temp[0],
setup, n_setup,
sce, &(sc->sc_mtx));
+ if (error == 0) {
+ if (n_in_frames > 0) {
+ error = ugen_allocate_blocks
+ (sc, sce, &(sce->in_queue), n_in_frames,
+ temp[0]->max_frame_size);
+ } else if (n_out_frames > 0) {
+ error = ugen_allocate_blocks
+ (sc, sce, &(sce->out_queue), n_out_frames,
+ temp[0]->max_frame_size);
+ }
+ if (error) {
+ usbd_transfer_unsetup(temp, n_setup);
+ }
+ }
+
mtx_lock(&sc->sc_mtx);
if(sce->state & UGEN_CLOSING)
@@ -445,7 +450,7 @@
}
static int
-__uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce,
+ugen_uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce,
u_int16_t context_bit, void *cp, int n,
struct uio *uio)
{
@@ -474,6 +479,31 @@
}
static int
+ugen_usb_uiomove(struct ugen_softc *sc, struct ugen_endpoint *sce,
+ struct usbd_page_cache *pc, struct uio *uio,
+ uint32_t pc_offset, uint32_t len, uint16_t context_bit)
+{
+ int error;
+
+ sce->state |= context_bit;
+
+ mtx_unlock(&sc->sc_mtx);
+
+ error = usbd_uiomove(pc, uio, pc_offset, len);
+
+ mtx_lock(&sc->sc_mtx);
+
+ sce->state &= ~context_bit;
+
+ if(sce->state & UGEN_CLOSING)
+ {
+ wakeup(sce);
+ error = EINTR;
+ }
+ return error;
+}
+
+static int
ugenopen(struct cdev *dev, int flag, int mode, struct thread *p)
{
struct ugen_softc *sc = DEV2SC(dev);
@@ -592,7 +622,6 @@
static int
ugen_open_pipe_write(struct ugen_softc *sc, struct ugen_endpoint *sce)
{
- u_int16_t isize;
usbd_status err;
mtx_assert(&sc->sc_mtx, MA_OWNED);
@@ -612,7 +641,6 @@
usbd_config[1].direction = UE_DIR_ANY;
usbd_config[1].timeout = 1000; /* 1 second */
usbd_config[1].interval = 50; /* 50 milliseconds */
- usbd_config[1].flags = 0;
usbd_config[1].bufsize = sizeof(usb_device_request_t);
usbd_config[1].callback = &ugen_write_clear_stall_callback;
@@ -622,18 +650,18 @@
usbd_config[0].callback = &ugen_default_write_callback;
usbd_config[0].interval = USBD_DEFAULT_INTERVAL;
usbd_config[0].timeout = sce->in_timeout;
+ usbd_config[0].flags.proxy_buffer = 1;
switch(ed->bmAttributes & UE_XFERTYPE)
{
case UE_INTERRUPT:
case UE_BULK:
- usbd_config[0].flags = 0;
usbd_config[0].bufsize = UGEN_BULK_BUFFER_SIZE;
if(__usbd_transfer_setup
(sc, sce, UGEN_WR_CFG,
sc->sc_udev, sce->pipe_out->iface_index,
- &sce->xfer_out[0], &usbd_config[0], 2))
+ &sce->xfer_out[0], &usbd_config[0], 2, 0, 0))
{
return (EIO);
}
@@ -643,11 +671,6 @@
break;
case UE_ISOCHRONOUS:
- isize = usbd_get_max_frame_size(ed);
-
- /* the maximum frame size is validated
- * by "usbd_fill_iface_data()"
- */
if(usbd_get_speed(sc->sc_udev) == USB_SPEED_HIGH)
{
@@ -658,15 +681,8 @@
sce->out_frames = UGEN_HW_FRAMES;
}
- if(ugen_allocate_blocks
- (sc, sce, UGEN_WR_CFG,
- &sce->out_queue, sce->out_frames * 10, isize) == 0)
- {
- return ENOMEM;
- }
-
- usbd_config[0].flags = USBD_SHORT_XFER_OK;
- usbd_config[0].bufsize = isize * sce->out_frames;
+ usbd_config[0].flags.short_xfer_ok = 1;
+ usbd_config[0].bufsize = 0; /* use default */
usbd_config[0].frames = sce->out_frames;
usbd_config[0].callback = &ugenisoc_write_callback;
usbd_config[0].timeout = 0;
@@ -677,11 +693,11 @@
err = __usbd_transfer_setup
(sc, sce, UGEN_WR_CFG,
sc->sc_udev, sce->pipe_out->iface_index,
- sce->xfer_out, usbd_config, 2);
+ sce->xfer_out, usbd_config, 2,
+ 0, 10 * sce->out_frames);
if(err)
{
- ugen_free_blocks(&sce->out_queue);
return (EIO);
}
break;
@@ -702,7 +718,6 @@
static int
ugen_open_pipe_read(struct ugen_softc *sc, struct ugen_endpoint *sce)
{
- int isize;
usbd_status err;
mtx_assert(&sc->sc_mtx, MA_OWNED);
@@ -722,7 +737,6 @@
usbd_config[1].direction = UE_DIR_ANY;
usbd_config[1].timeout = 1000; /* 1 second */
usbd_config[1].interval = 50; /* 50 milliseconds */
- usbd_config[1].flags = 0;
usbd_config[1].bufsize = sizeof(usb_device_request_t);
usbd_config[1].callback = &ugen_read_clear_stall_callback;
@@ -730,30 +744,22 @@
usbd_config[0].endpoint = ed->bEndpointAddress & UE_ADDR;
usbd_config[0].direction = UE_DIR_IN;
usbd_config[0].timeout = sce->in_timeout;
+ usbd_config[0].flags.proxy_buffer = 1;
switch(ed->bmAttributes & UE_XFERTYPE)
{
case UE_INTERRUPT:
- isize = usbd_get_max_frame_size(ed);
- usbd_config[0].flags = USBD_SHORT_XFER_OK;
+ usbd_config[0].flags.short_xfer_ok = 1;
usbd_config[0].callback = &ugen_interrupt_callback;
- usbd_config[0].bufsize = isize;
+ usbd_config[0].bufsize = 0; /* use "wMaxPacketSize" */
usbd_config[0].interval = USBD_DEFAULT_INTERVAL;
usbd_config[0].timeout = 0;
- if(ugen_allocate_blocks
- (sc, sce, UGEN_RD_CFG,
- &sce->in_queue, 1, isize) == 0)
- {
- return ENOMEM;
- }
-
if(__usbd_transfer_setup
(sc, sce, UGEN_RD_CFG,
sc->sc_udev, sce->pipe_in->iface_index,
- &sce->xfer_in[0], &usbd_config[0], 2))
+ &sce->xfer_in[0], &usbd_config[0], 2, 1, 0))
{
- ugen_free_blocks(&sce->in_queue);
return (EIO);
}
@@ -765,15 +771,16 @@
break;
case UE_BULK:
- usbd_config[0].flags = ((sce->state & UGEN_SHORT_OK) ?
- USBD_SHORT_XFER_OK : 0);
+ if (sce->state & UGEN_SHORT_OK) {
+ usbd_config[0].flags.short_xfer_ok = 1;
+ }
usbd_config[0].callback = &ugen_default_read_callback;
usbd_config[0].bufsize = UGEN_BULK_BUFFER_SIZE;
if(__usbd_transfer_setup
(sc, sce, UGEN_RD_CFG,
sc->sc_udev, sce->pipe_in->iface_index,
- &sce->xfer_in[0], &usbd_config[0], 2))
+ &sce->xfer_in[0], &usbd_config[0], 2, 0, 0))
{
return (EIO);
}
@@ -784,8 +791,6 @@
case UE_ISOCHRONOUS:
- isize = usbd_get_max_frame_size(ed);
-
/* the maximum frame size is validated
* by "usbd_fill_iface_data()"
*/
@@ -799,15 +804,8 @@
sce->in_frames = UGEN_HW_FRAMES;
}
- if(ugen_allocate_blocks
- (sc, sce, UGEN_RD_CFG,
- &sce->in_queue, sce->in_frames * 10, isize) == 0)
- {
- return ENOMEM;
- }
-
- usbd_config[0].flags = USBD_SHORT_XFER_OK;
- usbd_config[0].bufsize = isize * sce->in_frames;
+ usbd_config[0].flags.short_xfer_ok = 1;
+ usbd_config[0].bufsize = 0; /* use default */
usbd_config[0].frames = sce->in_frames;
usbd_config[0].callback = &ugenisoc_read_callback;
usbd_config[0].timeout = 0;
@@ -819,11 +817,11 @@
err = __usbd_transfer_setup
(sc, sce, UGEN_RD_CFG,
sc->sc_udev, sce->pipe_in->iface_index,
- sce->xfer_in, usbd_config, 2);
+ sce->xfer_in, usbd_config, 2,
+ sce->in_frames * 10, 0);
if(err)
{
- ugen_free_blocks(&sce->in_queue);
return (EIO);
}
@@ -891,7 +889,7 @@
}
sce->in_timeout = USBD_NO_TIMEOUT;
- sce->out_frame_size = -1; /* set maximum value */
+ sce->out_frame_size = 0-1; /* set maximum value */
sce->io_buffer_size = UGEN_BULK_BUFFER_SIZE; /* set default value */
if((pipe->edesc->bEndpointAddress &
@@ -1058,7 +1056,7 @@
PRINTFN(10, ("transferring %d bytes\n", len));
/* copy data to user memory */
- error = __uiomove(sc, sce, UGEN_RD_UIO, ptr, len, uio);
+ error = ugen_uiomove(sc, sce, UGEN_RD_UIO, ptr, len, uio);
if(error) break;
@@ -1090,13 +1088,13 @@
xfer = sce->xfer_in[0];
/* update length */
- xfer->length = n;
+ xfer->frlengths[0] = n;
/* start transfer */
usbd_transfer_start(xfer);
- while ((xfer->flags & USBD_DEV_TRANSFERRING) ||
- (sce->xfer_in[1]->flags & USBD_DEV_TRANSFERRING)) {
+ while ((xfer->flags_int.transferring) ||
+ (sce->xfer_in[1]->flags_int.transferring)) {
/* wait for data */
@@ -1133,9 +1131,10 @@
}
PRINTFN(1, ("got %d of %d bytes\n", xfer->actlen, n));
- error = __uiomove
- (sc, sce, UGEN_RD_UIO,
- xfer->buffer, xfer->actlen, uio);
+
+ error = ugen_usb_uiomove
+ (sc, sce, xfer->frbuffers + 0, uio, 0,
+ xfer->actlen, UGEN_RD_UIO);
if(error || (xfer->actlen < n))
{
@@ -1207,8 +1206,10 @@
#endif
xfer = sce->xfer_out[0];
- error = __uiomove
- (sc, sce, UGEN_WR_UIO, xfer->buffer, n, uio);
+ error = ugen_usb_uiomove
+ (sc, sce, xfer->frbuffers + 0, uio,
+ 0, n, UGEN_WR_UIO);
+
if(error)
{
break;
@@ -1217,13 +1218,13 @@
PRINTFN(1, ("transferred %d bytes\n", n));
/* update length */
- xfer->length = n;
+ xfer->frlengths[0] = n;
/* start transfer */
usbd_transfer_start(xfer);
- while ((xfer->flags & USBD_DEV_TRANSFERRING) ||
- (sce->xfer_out[1]->flags & USBD_DEV_TRANSFERRING)) {
+ while ((xfer->flags_int.transferring) ||
+ (sce->xfer_out[1]->flags_int.transferring)) {
/* wait for data */
@@ -1316,7 +1317,7 @@
*plen = uio->uio_resid;
}
- error = __uiomove(sc, sce, UGEN_WR_UIO, ptr, *plen, uio);
+ error = ugen_uiomove(sc, sce, UGEN_WR_UIO, ptr, *plen, uio);
if(error) break;
@@ -1432,7 +1433,7 @@
}
else
{
- bcopy(xfer->buffer, ptr, xfer->actlen);
+ usbd_copy_out(&(xfer->buf_data), 0, ptr, xfer->actlen);
if(xfer->actlen > *plen)
{
@@ -1469,6 +1470,7 @@
if (sce->read_stall) {
usbd_transfer_start(sce->xfer_in[1]);
} else {
+ xfer->frlengths[0] = xfer->max_data_length;
usbd_start_hardware(xfer);
}
return;
@@ -1506,13 +1508,12 @@
ugenisoc_read_callback(struct usbd_xfer *xfer)
{
struct ugen_endpoint *sce = xfer->priv_sc;
- u_int16_t *plen1;
+ u_int32_t *plen1;
u_int16_t *plen2;
- void *ptr1;
void *ptr2;
- u_int16_t isize;
+ uint32_t offset;
u_int16_t n;
USBD_CHECK_STATUS(xfer);
@@ -1522,10 +1523,9 @@
PRINTFN(5,("actlen=%d\n", xfer->actlen));
plen1 = xfer->frlengths;
- ptr1 = xfer->buffer;
- isize = usbd_get_max_frame_size(sce->pipe_in->edesc);
n = sce->in_frames;
+ offset = 0;
while(n--)
{
if(*plen1 != 0)
@@ -1542,14 +1542,15 @@
*plen1 = *plen2;
}
- bcopy(ptr1, ptr2, *plen1);
+ usbd_copy_out(xfer->frbuffers + 0, offset,
+ ptr2, *plen1);
*plen2 = *plen1;
ugen_inc_input_index(&sce->in_queue);
}
- ptr1 = ADD_BYTES(ptr1, isize);
+ offset += xfer->max_frame_size;
plen1++;
}
@@ -1562,11 +1563,10 @@
tr_setup:
tr_error:
- isize = usbd_get_max_frame_size(sce->pipe_in->edesc);
for(n = 0; n < sce->in_frames; n++)
{
/* setup size for next transfer */
- xfer->frlengths[n] = isize;
+ xfer->frlengths[n] = xfer->max_frame_size;
}
usbd_start_hardware(xfer);
return;
@@ -1576,24 +1576,26 @@
ugenisoc_write_callback(struct usbd_xfer *xfer)
{
struct ugen_endpoint *sce = xfer->priv_sc;
- u_int16_t *plen1;
- u_int16_t len2;
-
- void *ptr1;
+ uint32_t *plen1;
void *ptr2;
- u_int16_t isize;
+ uint32_t offset;
+ uint16_t len2;
u_int16_t n;
USBD_CHECK_STATUS(xfer);
+ tr_error:
+ if (xfer->error == USBD_CANCELLED) {
+ return;
+ }
+
tr_transferred:
tr_setup:
plen1 = xfer->frlengths;
- ptr1 = xfer->buffer;
- isize = usbd_get_max_frame_size(sce->pipe_out->edesc);
+ offset = 0;
n = sce->out_frames;
while(n--)
{
@@ -1604,18 +1606,17 @@
break;
}
- if(len2 > isize)
- {
- len2 = isize;
+ if (len2 > xfer->max_frame_size) {
+ len2 = xfer->max_frame_size;
}
- bcopy(ptr2, ptr1, len2);
+ usbd_copy_in(xfer->frbuffers + 0, offset, ptr2, len2);
*plen1 = len2;
ugen_inc_output_index(&sce->out_queue);
- ptr1 = ADD_BYTES(ptr1, len2);
+ offset += len2;
plen1++;
}
@@ -1631,9 +1632,7 @@
}
selwakeuppri(&sce->selinfo, PZERO);
- if(n)
- {
- tr_error:
+ if (n > 0) {
usbd_start_hardware(xfer);
}
return;
@@ -1671,7 +1670,7 @@
ugen_destroy_devnodes(sc, 1);
/* change setting */
- if(usbreq_set_interface(sc->sc_udev, ifaceidx, altno))
+ if(usbd_set_alt_interface_index(sc->sc_udev, ifaceidx, altno))
{
return EIO;
}
@@ -1706,8 +1705,7 @@
}
else
{
- if(usbreq_get_config_desc(udev, index, &cdescr))
- {
+ if (usbreq_get_config_desc(udev, NULL, &cdescr, index)) {
return (0);
}
len = UGETW(cdescr.wTotalLength);
@@ -1721,8 +1719,8 @@
{
return 0;
}
- if(usbreq_get_config_desc_full(udev, index, cdesc, len))
- {
+
+ if (usbreq_get_config_desc_full(udev, NULL, cdesc, len, index)) {
free(cdesc, M_TEMP);
return (0);
}
@@ -1749,6 +1747,7 @@
void *data = 0;
int error = 0;
int len;
+ uint16_t actlen;
u_int8_t conf;
u_int8_t alt;
@@ -1803,9 +1802,9 @@
goto done;
case USB_GET_FRAME_SIZE:
- if(sce->pipe_in)
+ if(sce->xfer_in[0])
{
- *(int *)addr = usbd_get_max_frame_size(sce->pipe_in->edesc);
+ *(int *)addr = sce->xfer_in[0]->max_frame_size;
}
else
{
@@ -1871,7 +1870,7 @@
break;
#endif
case USB_GET_CONFIG:
- error = usbreq_get_config(sc->sc_udev, &conf);
+ error = usbreq_get_config(sc->sc_udev, NULL, &conf);
if(error)
{
error = EIO;
@@ -2020,10 +2019,10 @@
break;
case USB_GET_STRING_DESC:
#define si ((struct usb_string_desc *)addr)
- if(usbreq_get_string_desc
- (sc->sc_udev, si->usd_string_index,
- si->usd_language_id, &si->usd_desc, NULL))
- {
+ if (usbreq_get_string_desc
+ (sc->sc_udev, NULL, &si->usd_desc,
+ sizeof(si->usd_desc), si->usd_language_id,
+ si->usd_string_index)) {
error = EINVAL;
break;
}
@@ -2080,11 +2079,14 @@
}
}
- if(usbd_do_request_flags
- (sc->sc_udev, &ur->ucr_request, data,
- (ur->ucr_flags & USBD_SHORT_XFER_OK), &ur->ucr_actlen,
- USBD_DEFAULT_TIMEOUT))
- {
+ error = usbd_do_request_flags
+ (sc->sc_udev, NULL, &ur->ucr_request, data,
+ (ur->ucr_flags & USBD_SHORT_XFER_OK), &actlen,
+ USBD_DEFAULT_TIMEOUT);
+
+ ur->ucr_actlen = actlen;
+
+ if (error) {
error = EIO;
break;
}
@@ -2101,8 +2103,7 @@
break;
case USB_GET_DEVICEINFO:
- usbd_fill_deviceinfo(sc->sc_udev,
- (struct usb_device_info *)addr, 1);
+ usbd_fill_deviceinfo(sc->sc_udev, (void *)addr);
break;
default:
error = EINVAL;
More information about the p4-projects
mailing list