USB MSC BBB Device Interface driver
[USB Device Framework]

Collaboration diagram for USB MSC BBB Device Interface driver:

Data Structures

struct  msc_interface
 A Mass Storage Class interface instance. More...

Defines

#define MSC_MAX_NR_SEGS   (2)
 Maximum number of pending block buffer segments.
#define MSC_MAX_SERIAL_LEN   20
 Maximum number of characters in the device serial number.

Functions

static void msc_queue_empty (struct msc_interface *msc)
 Current transfer is done; run any registered busy callback functions and clear it.
static int msc_submit_read_buffers (struct msc_interface *msc, struct block_device *bdev, struct block_request *breq, uint32_t nr_blocks)
static void msc_read_worker (struct msc_interface *msc)
static void msc_do_read (struct msc_interface *msc, struct udc *udc, struct usb_msc_cbw *cbw, uint32_t lba, uint32_t nr_blocks)
static int msc_submit_write_data_req (struct msc_interface *msc, struct block_device *bdev, uint32_t nr_blocks)
static void msc_write_worker (void *data)
status_t udi_msc_enable (struct udc *udc, struct udm_interface *iface, uint16_t setting)
 Enable the MSC interface.
void udi_msc_disable (struct udc *udc, struct udm_interface *iface)
 Disable the MSC interface.
status_t udi_msc_setup (struct udc *udc, struct udm_interface *iface, struct usb_setup_req *req)
 Handle a setup request directed at the MSC interface.
status_t udi_msc_get_iface_descriptor (struct udm_interface *iface, struct usb_request *req, enum usb_device_speed speed, uint16_t len)
 Get the interface descriptor for the MSC interface.
void udi_msc_free_descriptor (struct udm_interface *iface, struct usb_request *req)
 Free the memory allocated by msc_get_iface_descriptor().
void udi_msc_set_busy (struct udm_interface *iface, uint16_t asc, void(*queue_empty)(void *data), void *data)
 Reject data transfer requests.
void udi_msc_set_ready (struct udm_interface *iface)
 Allow data transfer requests.

Detailed Description

This driver implements a USB Mass Storage Class Bulk-only interface. Command, data and status transfers are all sent over two Bulk endpoints (one in and one out); also known as Bulk-Bulk-Bulk (BBB). This is the approach which has proven to give the best performance while using the least amount of resources (e.g. endpoints); other approaches like Command-Bulk-Interrupt (CBI) are not recommended for new devices according to the MSC Specification Overview.

This driver aims to conform with the following standards:


Define Documentation

#define MSC_MAX_NR_SEGS   (2)

Maximum number of pending block buffer segments.

Definition at line 78 of file msc_bulk.c.

Referenced by msc_read_worker(), and msc_write_worker().

#define MSC_MAX_SERIAL_LEN   20

Maximum number of characters in the device serial number.

Note that there's usually no point in having more than 12 characters.

Definition at line 71 of file udi_msc_bulk.h.


Function Documentation

static void msc_do_read ( struct msc_interface msc,
struct udc udc,
struct usb_msc_cbw cbw,
uint32_t  lba,
uint32_t  nr_blocks 
) [static]
static void msc_queue_empty ( struct msc_interface msc  )  [static]

Current transfer is done; run any registered busy callback functions and clear it.

For internal use only.

Definition at line 229 of file msc_bulk.c.

References msc_interface::busy_cb, msc_interface::busy_cb_data, cpu_irq_restore(), cpu_irq_save(), dbg_verbose, msc_interface::not_ready, and msc_interface::xfer_in_progress.

static void msc_read_worker ( struct msc_interface msc  )  [static]

For internal use only.

This function is called each time one of the following happens:

  • A USB read data request is done
  • The block device has started processing our request

The function will then try to keep both the block device and the USB controller as busy as possible by submitting new requests and buffer lists.

Definition at line 1111 of file msc_bulk.c.

References assert, atomic_read(), msc_interface::bdev, msc_interface::blk_blocks_pending, blkdev_get_block_size(), msc_interface::block_req, msc_interface::blocks_queued, msc_interface::blocks_total, cpu_irq_disable, cpu_irq_enable, dbg_verbose, MSC_MAX_NR_SEGS, msc_submit_read_buffers(), msc_interface::queue_locked, and block_request::status.

static int msc_submit_read_buffers ( struct msc_interface msc,
struct block_device bdev,
struct block_request breq,
uint32_t  nr_blocks 
) [static]

For internal use only.

Submit a list of buffers for storing data read from the block device. We will stop submitting buffers when

  • we have submitted enough to store all the data we intend to read, or
  • we have reached the maximum amount of data for a single buffer list, or
  • there's no more buffer memory available, or
  • the request was ended prematurely
Returns:
The number of blocks covered by the submitted buffers

Definition at line 1067 of file msc_bulk.c.

References atomic_add(), atomic_sub(), msc_interface::blk_blocks_pending, blkdev_get_block_size(), block_submit_buf_list(), msc_interface::blocks_queued, dbg_verbose, slist_init(), and unlikely.

Referenced by msc_do_read(), and msc_read_worker().

static int msc_submit_write_data_req ( struct msc_interface msc,
struct block_device bdev,
uint32_t  nr_blocks 
) [static]

For internal use only.

Submit a USB OUT request for receiving data to be written to the block device. We will add buffers to the request until

  • we have submitted enough to receive all the data we intend to write, or
  • we have reached the maximum amount of data for a single buffer list, or
  • there's no more buffer memory available
Returns:
The number of blocks covered by the submitted request

Definition at line 1366 of file msc_bulk.c.

References atomic_inc, blkdev_get_block_size(), msc_interface::blocks_queued, usb_request::buf_list, msc_interface::bulk_out_ep, usb_request::context, dbg_verbose, usb_request::req_done, msc_interface::udc, udc_ep_submit_out_req(), unlikely, usb_req_alloc(), usb_req_free(), and msc_interface::usb_reqs_pending.

Referenced by msc_write_worker().

static void msc_write_worker ( void *  data  )  [static]

For internal use only.

This function is called each time one of the following happens:

  • The block device has started processing our write request
  • The block device is done processing one buffer list

The function will then try to keep both the block device and the USB controller as busy as possible by submitting new requests and buffer lists.

Definition at line 1409 of file msc_bulk.c.

References assert, atomic_read(), msc_interface::bdev, msc_interface::block_req, msc_interface::blocks_queued, msc_interface::blocks_total, cpu_irq_disable, cpu_irq_enable, dbg_verbose, MSC_MAX_NR_SEGS, msc_submit_write_data_req(), msc_interface::queue_locked, block_request::status, and msc_interface::usb_reqs_pending.

void udi_msc_disable ( struct udc udc,
struct udm_interface iface 
)

Disable the MSC interface.

This function is normally called by the UDM layer, but the application may call it directly if the UDM layer isn't used.

Parameters:
udc The USB Device Controller which received the request
iface The UDM interface object representing this interface
status_t udi_msc_enable ( struct udc udc,
struct udm_interface iface,
uint16_t  setting 
)

Enable the MSC interface.

This function is normally called by the UDM layer, but the application may call it directly if the UDM layer isn't used.

Parameters:
udc The USB Device Controller which received the Set Configuration or Set Interface request.
iface The UDM interface object representing this interface
setting The alternate setting to be enabled. If a Set Interface request was received, pass wValue converted to native endian; otherwise, pass 0.
Return values:
STATUS_OK The interface was successfully enabled
STATUS_INVALID_ARG setting is not supported
negative Failed to enable the interface
void udi_msc_free_descriptor ( struct udm_interface iface,
struct usb_request req 
)

Free the memory allocated by msc_get_iface_descriptor().

This function is normally called by the UDM layer, but the application may call it directly if the UDM layer isn't used.

After the configuration descriptor has been successfully sent to the host, this function should be called for each interface in the same order that get_iface_descriptor() was called earlier as long as there are buffers left in req's buffer list. The buffers used by the CDC Data Class Interface are removed from req's buffer list.

Parameters:
iface The UDM interface object representing this interface
req The USB request which was used to send the configuration descriptor
status_t udi_msc_get_iface_descriptor ( struct udm_interface iface,
struct usb_request req,
enum usb_device_speed  speed,
uint16_t  len 
)

Get the interface descriptor for the MSC interface.

This function is normally called by the UDM layer, but the application may call it directly if the UDM layer isn't used.

Parameters:
iface The UDM interface object representing this interface
req The USB request being used to send the configuration descriptor. Zero or more buffers containing the interface descriptor data will be added to this request.
speed Get interface descriptors matching this speed. May be different from the current speed if the "other speed" configuration descriptor was requested.
len The number of bytes available for the descriptor data
Returns:
The number of bytes to be sent assuming len is large enough. May be more than the number of bytes actually queued for transfer if it was limited by len. Use this value to calculate the wTotalLength field of the configuration descriptor.
void udi_msc_set_busy ( struct udm_interface iface,
uint16_t  asc,
void(*)(void *data)  queue_empty,
void *  data 
)

Reject data transfer requests.

After the queue_empty callback has been called, all data transfer requests from the host are rejected with sense key NOT_READY and Additional Sense Code (Qualifier) as specified by asc.

Parameters:
iface The MSC interface
asc ASC/ASCQ pair to return in the sense data
queue_empty Callback to be called after any ongoing transfers have completed
data Arbitrary data pointer to be passed to queue_empty
void udi_msc_set_ready ( struct udm_interface iface  ) 

Allow data transfer requests.

After this function returns, the MSC interface iface will no longer reject data transfers from the host.

status_t udi_msc_setup ( struct udc udc,
struct udm_interface iface,
struct usb_setup_req req 
)

Handle a setup request directed at the MSC interface.

This function is normally called by the UDM layer, but the application may call it directly if the UDM layer isn't used.

Parameters:
udc The USB Device Controller which received the request
iface The UDM interface object representing this interface
setup The unparsed SETUP request to be handled
Return values:
STATUS_OK The request was handled successfully
negative The request failed, so ep0 should be STALLed.
Generated on Thu Apr 29 14:10:35 2010 for xplain-bc by  doxygen 1.6.3