Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
usb:usbperiphapi [2009/05/21 22:31] – AndrewThompsonusb:usbperiphapi [2009/05/22 06:14] (current) – AndrewThompson
Line 1: Line 1:
-X+Includes 
 + 
 +<code> 
 +#include <dev/usb/usb.h> 
 +#include <dev/usb/usbdi.h> 
 +</code> 
 + 
 +<code> 
 +usb_error_t     usb_pipe_open(struct usb_device *udev, 
 +            const uint8_t *ifaces, struct usb_pipe **, 
 +            const struct usb_config *, int count, 
 +            void *priv); 
 +void            usb_pipe_halt(struct usb_pipe *); 
 +void            usb_pipe_ready(struct usb_pipe *); 
 +void            usb_pipe_drain(struct usb_pipe *); 
 +void            usb_pipe_close(struct usb_pipe **, int count); 
 +void            usb_clear_stall(struct usb_pipe *); 
 +struct usb_urb *usb_get_urb(struct usb_pipe *, int flags); 
 +int             usb_set_frame_data(struct usb_urb *, int index, void *, int len); 
 +int             usb_copyin_urb(struct usb_urb *, void *, int offset, int len); 
 +int             usb_copyout_urb(struct usb_urb *, void *, int offset, int len); 
 +void            usb_cancel_urb(struct usb_urb *); 
 +void            usb_free_urb(struct usb_urb *); 
 +void            usb_submit_urb(struct usb_pipe *, struct usb_urb *, int flags); 
 + 
 +</code> 
 + 
 +===== Structs ===== 
 +==== struct usb_pipe ==== 
 +A queue for processing urb pointers. Has one dma map and will reload the dma if the current urb is different to the one previously loaded. The pipe has a private mutex for queueing and dequeueing, it does not need to share the mutex with the driver. 
 + 
 +==== struct usb_urb ==== 
 +A data buffer. The memory can be preallocated (fixed size) or passed in from an external buffer. The urb has a single reference and does not need to be locked. 
 + 
 +Notes: 
 +  * usb_pipe_open() will preallocate the requested number of urb structures and keep on a free list 
 +  * usb_get_urb() will get a urb from the free list. 
 +  * usb_free_urb() does not actually free the memory, it puts the urb on the pipe free list 
 +  * usb_pipe_halt() cancels all pending urbs and sets the pipe to blocking 
 +  * usb_pipe_ready() will unblock the pipe and start processing anything in the urb queue 
 +  * usb_submit_urb() will put the urb on the processing list 
 + 
 +====== Examples (overly simplified to show basic working) ====== 
 + 
 +==== example 1, external buffer ==== 
 + 
 +<code> 
 +ep_config { 
 +  .type = UE_BULK, 
 +  .endpoint = UE_ADDR_ANY, 
 +  .direction = UE_DIR_OUT, 
 +  .bufsize = 0, /* external */ 
 +  .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 
 +  .callback = write_callback, 
 +  .timeout = 5000,        /* ms */ 
 +  .min_urb = 8, 
 +  .max_urb = 8, 
 +} { 
 +  .type = UE_BULK, 
 +  .endpoint = UE_ADDR_ANY, 
 +  .direction = UE_DIR_IN, 
 +  .bufsize = 0, /* external */ 
 +  .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 
 +  .callback = read_callback, 
 +  .min_urb = 8, 
 +  .max_urb = 8, 
 +}  
 + 
 +attach() 
 + error = usb_pipe_open(uaa->device, 
 +         &iface_index, sc->sc_xfer, ep_config, 
 +         XXX_N_TRANSFER, sc); 
 + 
 +detach() 
 + usb_pipe_close(sc->sc_xfer, XXX_N_TRANSFER); 
 + 
 +init() 
 + /* will return up to 'max_urb' times */ 
 + while((urb = usb_get_urb(sc->sc_readxfer) != NULL) { 
 +   m = m_getcl(M_WAIT, MT_DATA, M_PKTHDR); 
 +   usb_set_frame_data(urb, 0, m->data, m->len); 
 +   usb_set_priv(urb, m); 
 +   usb_submit_urb(urb); 
 + } 
 + usb_pipe_ready(sc->sc_readxfer); 
 + usb_pipe_ready(sc->sc_writexfer); 
 + 
 +stop() 
 + usb_pipe_halt(sc->sc_readxfer); 
 + usb_pipe_halt(sc->sc_writexfer); 
 + 
 +start(m) 
 + urb = usb_get_urb(sc->sc_writexfer); 
 + if (urb == NULL) 
 +   return; 
 + usb_set_frame_data(urb, 0, m->data, m->len); 
 + usb_set_priv(urb, m); 
 + usb_submit_urb(urb); 
 + 
 +write_callback(urb, error) 
 + pipe = urb->pipe; 
 + if (error) 
 +   usb_clear_stall(pipe); 
 + m = usb_get_priv(urb); 
 + usb_free_urb(urb); 
 + m_freem(m); 
 + start() /* try to send more */ 
 + 
 +read_callback(urb, error) 
 + pipe = urb->pipe; 
 + if (error) 
 +   usb_clear_stall(pipe); 
 + m = usb_get_priv(urb); 
 + mnew = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 
 + if (!mnew) { 
 +    ifp->if_ierrors++; 
 +    goto skip; 
 + } 
 + m_input(m); 
 + usb_set_frame_data(urb, 0, mnew->data, mnew->len); 
 + usb_set_priv(urb, mnew); 
 +skip: 
 + usb_submit_urb(urb); 
 +</code> 
 + 
 +==== example 2, internal buffer ==== 
 + 
 +<code> 
 +ep_config { 
 +  .type = UE_BULK, 
 +  .endpoint = UE_ADDR_ANY, 
 +  .direction = UE_DIR_OUT, 
 +  .bufsize = 512, 
 +  .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 
 +  .callback = write_callback, 
 +  .timeout = 5000,        /* ms */ 
 +  .min_urb = 4, 
 +  .max_urb = 4, 
 +} { 
 +  .type = UE_BULK, 
 +  .endpoint = UE_ADDR_ANY, 
 +  .direction = UE_DIR_IN, 
 +  .bufsize = 512, 
 +  .flags = {.pipe_bof = 1,.force_short_xfer = 1,}, 
 +  .callback = read_callback, 
 +  .max_urb = 4, 
 +}  
 + 
 +attach() 
 + error = usb_pipe_open(uaa->device, 
 +         &iface_index, sc->sc_xfer, ep_config, 
 +         XXX_N_TRANSFER, sc); 
 + 
 +detach() 
 + usb_pipe_close(sc->sc_xfer, XXX_N_TRANSFER); 
 + 
 +ttyopen() 
 + /* will return up to 'max_urb' times */ 
 + while((urb = usb_get_urb(sc->sc_readxfer) != NULL) { 
 +   usb_submit_urb(urb); 
 + } 
 + usb_pipe_ready(sc->sc_readxfer); 
 + usb_pipe_ready(sc->sc_writexfer); 
 + 
 +ttyclose() 
 + usb_pipe_halt(sc->sc_readxfer); 
 + usb_pipe_halt(sc->sc_writexfer); 
 + 
 +ttywakeup() 
 + urb = usb_get_urb(sc->sc_writexfer); 
 + if (urb == NULL) 
 +   return; /* all buffers in flight */ 
 + ttydisc_getc(urb->data, urb->len); 
 + usb_submit_urb(urb); 
 + 
 +write_callback(urb, error) 
 + pipe = urb->pipe; 
 + if (error) 
 +   usb_clear_stall(pipe); 
 + /* refill buffer */ 
 + if (ttydisc_getc(urb->data, urb->len)) 
 +   usb_submit_urb(urb); 
 + else 
 +   usb_free_urb(urb); 
 + 
 +read_callback(urb, error) 
 + pipe = urb->pipe; 
 + if (error) 
 +   usb_clear_stall(pipe); 
 + tty_rint(urb->data, urb->len); 
 + usb_submit_urb(urb); 
 +</code>
  
  • usb/usbperiphapi.1242945102.txt.gz
  • Last modified: 2009/05/21 22:31
  • by AndrewThompson