initial commit

This commit is contained in:
2024-12-15 00:34:01 +06:00
commit 31efbc726f
1576 changed files with 657692 additions and 0 deletions

View File

@@ -0,0 +1,183 @@
#ifndef USBD_MSC_H
#define USBD_MSC_H
#include "usb.h"
#include "usb_gadget.h"
#include "core/inc/usb_composite.h"
#include "msc/inc/usbd_msc_config.h"
/* config usb msc device debug inforation */
#define USBD_MSC_DEBUG 0
#if USBD_MSC_DEBUG
#define USBD_PRINTF(fmt, args...) DBG_8195A("\n\r%s: " fmt, __FUNCTION__, ## args)
#define USBD_ERROR(fmt, args...) DBG_8195A("\n\r%s: " fmt, __FUNCTION__, ## args)
#define USBD_WARN(fmt, args...) DBG_8195A("\n\r%s: " fmt, __FUNCTION__, ## args)
#define FUN_ENTER DBG_8195A("\n\r%s ==>\n", __func__)
#define FUN_EXIT DBG_8195A("\n\r%s <==\n", __func__)
#define FUN_TRACE DBG_8195A("\n\r%s:%d \n", __func__, __LINE__)
#else
#define USBD_PRINTF(fmt, args...)
#define USBD_ERROR(fmt, args...) DBG_8195A("\n\r%s: " fmt, __FUNCTION__, ## args)
#define USBD_WARN(fmt, args...)
#define FUN_ENTER
#define FUN_EXIT
#define FUN_TRACE
#endif
/* MSC Request Codes */
#define MSC_REQUEST_RESET 0xFF
#define MSC_REQUEST_GET_MAX_LUN 0xFE
/* MSC LUN */
#define MSC_MAX_LOGIC_UNIT_NUMBER 1
enum data_direction{
DATA_DIR_UNKNOWN = 0,
DATA_DIR_FROM_HOST,
DATA_DIR_TO_HOST,
DATA_DIR_NONE
};
typedef enum _disk_type{
DISK_SDCARD,
DISK_FLASH
}disk_type;
//structure predefine
struct msc_dev;
struct msc_bufhd;
struct msc_opts{
int (*disk_init)(void);
int (*disk_deinit)(void);
int (*disk_getcapacity)(u32* sectors);
int (*disk_read)(u32 sector,u8 *buffer,u32 count);
int (*disk_write)(u32 sector,const u8 *buffer,u32 count);
};
struct msc_lun {
unsigned int initially_ro:1;
unsigned int ro:1;
unsigned int removable:1;
unsigned int cdrom:1;
unsigned int prevent_medium_removal:1;
unsigned int registered:1;
unsigned int info_valid:1;
unsigned int nofua:1;
u32 sense_data;
u32 sense_data_info;
u32 unit_attention_data;
u64 file_length;
unsigned int num_sectors; /* */
unsigned int blkbits; /* Bits of logical block size
of bound block device */
unsigned int blksize; /* logical block size of bound block device */
const char *name; /* "lun.name" */
unsigned int lba; // the current read and write logical block address
u8 is_open;
_mutex lun_mutex;
struct msc_opts *lun_opts;
};
struct msc_common{
struct msc_dev *mscdev;
struct msc_lun **luns;
struct msc_lun *curlun;
struct usb_gadget *gadget;
struct usb_ep *ep0;
struct usb_request *req0; /* for control responses */
/* scsi cbw relevant */
enum data_direction data_dir;
u32 data_size;
u32 data_size_from_cmnd;
u32 tag;
u32 residue;
u32 usb_amount_left;
u8 scsi_cmnd[16]; // max command
u8 cmnd_size;
u8 lun; /* current lun*/
u8 nluns;
u8 nbufhd;
u8 nbufhd_a;
_list bufhd_pool;
_mutex bufhd_mutex;
/* bulk out cmd*/
_list boc_list;
_mutex boc_mutex;
/* bolk out data*/
_mutex bod_mutex;
_list bod_list;
/**/
struct msc_bufhd* curbh; // current buffer header
struct msc_bufhd* cbw_bh; // buffer header for CBW
struct msc_bufhd* csw_bh; // buffer header for CSW
unsigned int can_stall:1;
unsigned int phase_error:1;
unsigned int short_packet_received:1;
unsigned int bad_lun_okay:1;
unsigned int running:1;
};
typedef enum _bufhd_type{
BUFHD_CBW = 0,
BUFHD_CSW,
BUFHD_DATA,
}bufhd_type;
struct msc_bufhd{
u8* buf;
int buf_size;
bufhd_type type;
_list list;
struct usb_request *reqin; /* for bulkin responses */
struct usb_request *reqout;
};
struct msc_dev{
struct msc_common *common;
u16 interface_number;
u8 config;
struct usb_ep *in_ep;
struct usb_ep *out_ep;
unsigned int bulk_in_enabled:1;
unsigned int bulk_out_enabled:1;
const struct usb_endpoint_descriptor
*in, *out, *status;
// lock is held when accessing usb
struct task_struct msc_outCmdTask;
struct task_struct msc_outDataTask;
struct usb_function func;
};
u32 min(u32 value1,u32 value2);
int usbd_msc_halt_bulk_in_endpoint(struct msc_dev *mscdev);
void usbd_msc_put_bufhd(struct msc_common *common, struct msc_bufhd* bufhd);
struct msc_bufhd* usbd_msc_get_bufhd(struct msc_common *common);
int usbd_msc_bulk_in_transfer(struct msc_dev *mscdev, struct usb_request *req);
int usbd_msc_bulk_out_transfer(struct msc_dev *mscdev, struct usb_request *req);
/*
* N_bh : number of buffer header
* Size_bh: buffer size per buffer
* type:msc physical disk type
*/
int usbd_msc_init(int N_bh, int Size_bh, disk_type type);
void usbd_msc_deinit(void);
#endif

View File

@@ -0,0 +1,8 @@
#ifndef _USBD_MSC_CONFIG_H
#define _USBD_MSC_CONFIG_H
/* config usb MSC device buffer resource */
#define MSC_NBR_BUFHD 2 /* number of buffer header for bulk in/out data*/
#define MSC_BUFLEN (32*512)/* Default size of buffer length. Minmun of 512 byte*/
#endif

View File

@@ -0,0 +1,196 @@
#include "usb_ch9.h"
#include "usb_defs.h"
#include "usb_gadget.h"
// <i> Enable high-speed functionality (if device supports it)
#define USBD_HS_ENABLE 1
// define string index
#define STRING_MANUFACTURER 1
#define STRING_PRODUCT 2
#define STRING_SERIALNUMBER 3
#define STRING_INTERFACE 4
#define STRING_MSC 5
#define DEV_CONFIG_VALUE 1
#define DRIVER_DESC "USB Mass Storage"
#define DRIVER_VERSION "Feb 2016"
#define MANUFACTURER "Realtek Singapore Semiconductor"
static char string_manufacturer [50] = MANUFACTURER;
static char string_product [40] = DRIVER_DESC;
static char string_serial [20] = "0123456789";
struct usb_string
usbd_msc_strings [] = {
{ STRING_MANUFACTURER, string_manufacturer, },
{ STRING_PRODUCT, string_product, },
{ STRING_SERIALNUMBER, string_serial, },
{ STRING_INTERFACE, "USB MSC Interface", },
{ STRING_MSC, "USB MSC", },
};
struct usb_gadget_strings msc_stringtab = {
.language = 0x0409, /* en-us */
.strings = usbd_msc_strings,
};
struct usb_gadget_strings *dev_msc_strings[] = {
&msc_stringtab,
NULL,
};
static struct usb_device_descriptor
usbd_msc_device_desc = {
.bLength = sizeof usbd_msc_device_desc,
.bDescriptorType = USB_DT_DEVICE,
.bcdUSB = (0x0200),
.bDeviceClass = 0x00,// define in interface descriptor
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = 64, // this will be set automatically depends on ep0 setting
.idVendor = 0x0BDA,
.idProduct = 0x8195,
// .bcdDevice = ,
.iManufacturer = STRING_MANUFACTURER,
.iProduct = STRING_PRODUCT,
.iSerialNumber = STRING_SERIALNUMBER,
.bNumConfigurations=0x01,
};
#if 0
struct usb_config_descriptor
usbd_msc_config_desc = {
.bLength = sizeof usbd_msc_config_desc,
.bDescriptorType = USB_DT_CONFIG,
/* compute wTotalLength on the fly */
.bNumInterfaces = 1,
.bConfigurationValue = DEV_CONFIG_VALUE,
.iConfiguration = STRING_MSC,
.bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER,
.bMaxPower = 0x32,
};
#endif
#if USBD_HS_ENABLE
/* USB Device Qualifier Descriptor (for Full Speed) */
static struct usb_qualifier_descriptor
usbd_msc_qualifier_desc_FS = {
.bLength = sizeof usbd_msc_qualifier_desc_FS,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = 0x0200,
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = 64,
.bNumConfigurations = 0x01,
.bRESERVED = 0x00,
};
/* USB Device Qualifier Descriptor for High Speed */
static struct usb_qualifier_descriptor
usbd_msc_qualifier_desc_HS = {
.bLength = sizeof usbd_msc_qualifier_desc_HS,
.bDescriptorType = USB_DT_DEVICE_QUALIFIER,
.bcdUSB = 0x0200,
.bDeviceClass = 0x00,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = 64,
.bNumConfigurations = 0x01,
.bRESERVED = 0x00,
};
#else
/* USB Device Qualifier Descriptor (for Full Speed) */
static struct usb_qualifier_descriptor
usbd_msc_qualifier_desc_FS = { 0 };
/* USB Device Qualifier Descriptor for High Speed */
static struct usb_qualifier_descriptor
usbd_msc_qualifier_desc_HS = { 0 };
#endif
/* MSC Interface, Alternate Setting 0*/
struct usb_interface_descriptor
usbd_msc_intf_desc = {
.bLength = sizeof usbd_msc_intf_desc,
.bDescriptorType = USB_DT_INTERFACE,
.bInterfaceNumber = 0x00, // this will be assign automatically
.bAlternateSetting =0x00,
.bNumEndpoints = 0x02,
.bInterfaceClass = USB_CLASS_MASS_STORAGE,
.bInterfaceSubClass = US_SC_SCSI,
.bInterfaceProtocol = US_PR_BULK,
.iInterface = STRING_INTERFACE,
};
/* MSC Endpoints for Low-speed/Full-speed */
/* Endpoint, EP Bulk IN */
struct usb_endpoint_descriptor
usbd_msc_source_desc_FS = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = (64),
.bInterval = 0x00,
};
/* Endpoint, EP Bulk OUT */
struct usb_endpoint_descriptor
usbd_msc_sink_desc_FS = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = (64),
.bInterval = 0x00,
};
/* MSC Endpoints for High-speed */
/* Endpoint, EP Bulk IN */
struct usb_endpoint_descriptor
usbd_msc_source_desc_HS = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_IN,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = (512),
.bInterval = 0x00,
};
/* Endpoint, EP Bulk OUT */
struct usb_endpoint_descriptor
usbd_msc_sink_desc_HS = {
.bLength = USB_DT_ENDPOINT_SIZE,
.bDescriptorType = USB_DT_ENDPOINT,
.bEndpointAddress = USB_DIR_OUT,
.bmAttributes = USB_ENDPOINT_XFER_BULK,
.wMaxPacketSize = (512),
.bInterval = 0x00,
};
struct usb_descriptor_header *usbd_msc_descriptors_FS [] = {
/* data interface has no altsetting */
(struct usb_descriptor_header *) &usbd_msc_intf_desc,
(struct usb_descriptor_header *) &usbd_msc_source_desc_FS,
(struct usb_descriptor_header *) &usbd_msc_sink_desc_FS,
NULL,
};
struct usb_descriptor_header *usbd_msc_descriptors_HS [] = {
/* data interface has no altsetting */
(struct usb_descriptor_header *) &usbd_msc_intf_desc,
(struct usb_descriptor_header *) &usbd_msc_source_desc_HS,
(struct usb_descriptor_header *) &usbd_msc_sink_desc_HS,
NULL,
};

View File

@@ -0,0 +1,110 @@
#ifndef USBD_SCSI_H
#define USBD_SCSI_H
#include "basic_types.h"
#include "msc/inc/usbd_msc.h"
#define MAX_COMMAND_SIZE 16
#define MSC_MAX_LUNS 8
/* SCSI Commands */
#define SCSI_FORMAT_UNIT 0x04
#define SCSI_INQUIRY 0x12
#define SCSI_MODE_SELECT6 0x15
#define SCSI_MODE_SELECT10 0x55
#define SCSI_MODE_SENSE6 0x1A
#define SCSI_MODE_SENSE10 0x5A
#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E
#define SCSI_READ6 0x08
#define SCSI_READ10 0x28
#define SCSI_READ12 0xA8
#define SCSI_READ16 0x88
#define SCSI_READ_CAPACITY10 0x25
#define SCSI_READ_CAPACITY16 0x9E
#define SCSI_SYNCHRONIZE_CACHE 0x35
#define SCSI_REQUEST_SENSE 0x03
#define SCSI_START_STOP_UNIT 0x1B
#define SCSI_TEST_UNIT_READY 0x00
#define SCSI_WRITE6 0x0A
#define SCSI_WRITE10 0x2A
#define SCSI_WRITE12 0xAA
#define SCSI_WRITE16 0x8A
#define SCSI_VERIFY10 0x2F
#define SCSI_VERIFY12 0xAF
#define SCSI_VERIFY16 0x8F
#define SCSI_SEND_DIAGNOSTIC 0x1D
#define SCSI_READ_FORMAT_CAPACITIES 0x23
#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C
#define READ_CAPACITY10_DATA_LEN 0x08
#define MODE_SENSE10_DATA_LEN 0x08
#define MODE_SENSE6_DATA_LEN 0x04
#define REQUEST_SENSE_DATA_LEN 0x12
#define STANDARD_INQUIRY_DATA_LEN 0x24
/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */
#define SS_NO_SENSE 0
#define SS_COMMUNICATION_FAILURE 0x040800
#define SS_INVALID_COMMAND 0x052000
#define SS_INVALID_FIELD_IN_CDB 0x052400
#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100
#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500
#define SS_MEDIUM_NOT_PRESENT 0x023a00
#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302
#define SS_NOT_READY_TO_READY_TRANSITION 0x062800
#define SS_RESET_OCCURRED 0x062900
#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900
#define SS_UNRECOVERED_READ_ERROR 0x031100
#define SS_WRITE_ERROR 0x030c02
#define SS_WRITE_PROTECTED 0x072700
#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */
#define ASC(x) ((u8) ((x) >> 8))
#define ASCQ(x) ((u8) (x))
/*
* Bulk only data structures
*/
/* command block wrapper */
struct bulk_cb_wrap {
unsigned int Signature; /* contains 'USBC', denote bulk_cb_wrap */
unsigned int Tag; /* unique per command id */
unsigned int DataTransferLength; /* size of data for transfer */
unsigned char Flags; /* data transfer direction */
unsigned char Lun; /* LUN normally 0, (which command block is sent) */
unsigned char Length; /* length of the CDB */
unsigned char CDB[16]; /* max command */
};
#define US_BULK_CB_WRAP_LEN 31
#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */
#define US_BULK_FLAG_IN (1 << 7)
#define US_BULK_FLAG_OUT 0
/* command status wrapper */
struct bulk_cs_wrap {
unsigned int Signature; /* should = 'USBS' */
unsigned int Tag; /* same as original command, echoed by the device as received */
unsigned int Residue; /* amount not transferred */
unsigned char Status; /* execute command status */
};
#define US_BULK_CS_WRAP_LEN 13
#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */
// execute command status
#define US_BULK_STAT_OK 0
#define US_BULK_STAT_FAIL 1
#define US_BULK_STAT_PHASE 2
/* bulk-only class specific requests */
#define US_BULK_RESET_REQUEST 0xff
#define US_BULK_GET_MAX_LUN 0xfe
extern int usbd_msc_receive_cbw(struct msc_dev *mscdev, struct usb_request *req);
#endif

View File

@@ -0,0 +1,24 @@
#ifndef _GADEGT_DEBUG_H_
#define _GADGET_DEBUG_H_
#include "diag.h"
#define GADGET_DEBUG 0
#if GADGET_DEBUG
#define GADGET_PRINT(fmt, args...) DBG_8195A("\n\r[%s]: " fmt, __FUNCTION__, ## args)
#define GADGET_ERROR(fmt, args...) DBG_8195A("\n\r[%s]: " fmt, __FUNCTION__, ## args)
#define GADGET_WARN(fmt, args...) DBG_8195A("\n\r[%s]: " fmt, __FUNCTION__, ## args)
#define FUN_ENTER DBG_8195A("\n\r[%s ==>]\n", __func__)
#define FUN_EXIT DBG_8195A("\n\r[%s <==]\n", __func__)
#define FUN_TRACE DBG_8195A("\n\r[%s]:%d \n", __func__, __LINE__)
#else
#define GADGET_PRINT(fmt, args...)
#define GADGET_ERROR(fmt, args...) DBG_8195A("\n\r[%s]: " fmt, __FUNCTION__, ## args)
#define GADGET_WARN(fmt, args...)
#define FUN_ENTER
#define FUN_EXIT
#define FUN_TRACE
#endif
#endif

View File

@@ -0,0 +1,398 @@
#ifndef _USB_COMPOSITE_H_
#define _USB_COMPOSITE_H_
#include "usb_gadget.h"
#include "usb.h"
/*
* USB function drivers should return USB_GADGET_DELAYED_STATUS if they
* wish to delay the data/status stages of the control transfer till they
* are ready. The control transfer will then be kept from completing till
* all the function drivers that requested for USB_GADGET_DELAYED_STAUS
* invoke usb_composite_setup_continue().
*/
#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */
/* big enough to hold our biggest descriptor */
#define USB_COMP_EP0_BUFSIZ 1024+24
#define MAX_CONFIG_INTERFACES 16 /* arbitrary; max 255 */
// predefine structure
struct usb_composite_dev;
struct usb_composite_driver;
enum control_request_return_codes {
USBD_REQ_NOTSUPP = 0,
USBD_REQ_HANDLED = 1,
USBD_REQ_NEXT_CALLBACK = 2,
};
/**
* struct usb_composite_driver - groups configurations into a gadget
* @name: For diagnostics, identifies the driver.
* @dev: Template descriptor for the device, including default device
* identifiers.
* @strings: tables of strings, keyed by identifiers assigned during @bind
* and language IDs provided in control requests. Note: The first entries
* are predefined. The first entry that may be used is
* USB_GADGET_FIRST_AVAIL_IDX
* @max_speed: Highest speed the driver supports.
* @needs_serial: set to 1 if the gadget needs userspace to provide
* a serial number. If one is not provided, warning will be printed.
* @bind: (REQUIRED) Used to allocate resources that are shared across the
* whole device, such as string IDs, and add its configurations using
* @usb_add_config(). This may fail by returning a negative errno
* value; it should return zero on successful initialization.
* @unbind: Reverses @bind; called as a side effect of unregistering
* this driver.
* @disconnect: optional driver disconnect method
* @suspend: Notifies when the host stops sending USB traffic,
* after function notifications
* @resume: Notifies configuration when the host restarts USB traffic,
* before function notifications
* @gadget_driver: Gadget driver controlling this driver
*
* Devices default to reporting self powered operation. Devices which rely
* on bus powered operation should report this in their @bind method.
*
* Before returning from @bind, various fields in the template descriptor
* may be overridden. These include the idVendor/idProduct/bcdDevice values
* normally to bind the appropriate host side driver, and the three strings
* (iManufacturer, iProduct, iSerialNumber) normally used to provide user
* meaningful device identifiers. (The strings will not be defined unless
* they are defined in @dev and @strings.) The correct ep0 maxpacket size
* is also reported, as defined by the underlying controller driver.
*/
struct usb_composite_driver {
const char *name;
const struct usb_device_descriptor *dev;
struct usb_gadget_strings **strings;
enum usb_device_speed max_speed;
unsigned needs_serial:1;
int (*bind)(struct usb_composite_dev *cdev);
int (*unbind)(struct usb_composite_dev *);
void (*disconnect)(struct usb_composite_dev *);
/* global suspend hooks */
void (*suspend)(struct usb_composite_dev *);
void (*resume)(struct usb_composite_dev *);
struct usb_gadget_driver gadget_driver;
};
/**
* struct usb_composite_device - represents one composite usb gadget
* @gadget: read-only, abstracts the gadget's usb peripheral controller
* @req: used for control responses; buffer is pre-allocated
* @os_desc_req: used for OS descriptors responses; buffer is pre-allocated
* @config: the currently active configuration
* @qw_sign: qwSignature part of the OS string
* @b_vendor_code: bMS_VendorCode part of the OS string
* @use_os_string: false by default, interested gadgets set it
* @os_desc_config: the configuration to be used with OS descriptors
*
* One of these devices is allocated and initialized before the
* associated device driver's bind() is called.
*
* OPEN ISSUE: it appears that some WUSB devices will need to be
* built by combining a normal (wired) gadget with a wireless one.
* This revision of the gadget framework should probably try to make
* sure doing that won't hurt too much.
*
* One notion for how to handle Wireless USB devices involves:
* (a) a second gadget here, discovery mechanism TBD, but likely
* needing separate "register/unregister WUSB gadget" calls;
* (b) updates to usb_gadget to include flags "is it wireless",
* "is it wired", plus (presumably in a wrapper structure)
* bandgroup and PHY info;
* (c) presumably a wireless_ep wrapping a usb_ep, and reporting
* wireless-specific parameters like maxburst and maxsequence;
* (d) configurations that are specific to wireless links;
* (e) function drivers that understand wireless configs and will
* support wireless for (additional) function instances;
* (f) a function to support association setup (like CBAF), not
* necessarily requiring a wireless adapter;
* (g) composite device setup that can create one or more wireless
* configs, including appropriate association setup support;
* (h) more, TBD.
*/
#define MAX_USER_CONTROL_CALLBACK 2
typedef int (*user_control_callback)(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl);
struct usb_composite_dev {
struct usb_gadget *gadget;
struct usb_request *req;
struct usb_request *os_desc_req;
struct usb_configuration *config;
//
// /* OS String is a custom (yet popular) extension to the USB standard. */
// u8 qw_sign[OS_STRING_QW_SIGN_LEN];
// u8 b_vendor_code;
// struct usb_configuration *os_desc_config;
// unsigned int use_os_string:1;
//
// /* private: */
// /* internals */
unsigned int suspended:1;
struct usb_device_descriptor desc;
//_LIST config_list;
dwc_list_link_t config_list; // by jimmy
//_LIST gstring_list;
dwc_list_link_t gstring_list;// by jimmy
struct usb_composite_driver *driver;
// u8 next_string_id;
// char *def_manufacturer;
//
// /* the gadget driver won't enable the data pullup
// * while the deactivation count is nonzero.
// */
// unsigned deactivations;
//
// /* the composite driver won't complete the control transfer's
// * data/status stages till delayed_status is zero.
// */
// int delayed_status;
//
// /* protects deactivations and delayed_status counts*/
_Lock lock;
/* for unstandard control request handler */
user_control_callback control_cb[MAX_USER_CONTROL_CALLBACK];
};
#if 0
#define container_of(p,t,n) (t*)((p)-&(((t*)0)->n))
static inline struct usb_composite_driver *to_cdriver(
struct usb_gadget_driver *gdrv)
{
return container_of(gdrv, struct usb_composite_driver, gadget_driver);
}
#endif
#if 1
/**
* struct usb_configuration - represents one gadget configuration
* @label: For diagnostics, describes the configuration.
* @strings: Tables of strings, keyed by identifiers assigned during @bind()
* and by language IDs provided in control requests.
* @descriptors: Table of descriptors preceding all function descriptors.
* Examples include OTG and vendor-specific descriptors.
* @unbind: Reverses @bind; called as a side effect of unregistering the
* driver which added this configuration.
* @setup: Used to delegate control requests that aren't handled by standard
* device infrastructure or directed at a specific interface.
* @bConfigurationValue: Copied into configuration descriptor.
* @iConfiguration: Copied into configuration descriptor.
* @bmAttributes: Copied into configuration descriptor.
* @MaxPower: Power consumtion in mA. Used to compute bMaxPower in the
* configuration descriptor after considering the bus speed.
* @cdev: assigned by @usb_add_config() before calling @bind(); this is
* the device associated with this configuration.
*
* Configurations are building blocks for gadget drivers structured around
* function drivers. Simple USB gadgets require only one function and one
* configuration, and handle dual-speed hardware by always providing the same
* functionality. Slightly more complex gadgets may have more than one
* single-function configuration at a given speed; or have configurations
* that only work at one speed.
*
* Composite devices are, by definition, ones with configurations which
* include more than one function.
*
* The lifecycle of a usb_configuration includes allocation, initialization
* of the fields described above, and calling @usb_add_config() to set up
* internal data and bind it to a specific device. The configuration's
* @bind() method is then used to initialize all the functions and then
* call @usb_add_function() for them.
*
* Those functions would normally be independent of each other, but that's
* not mandatory. CDC WMC devices are an example where functions often
* depend on other functions, with some functions subsidiary to others.
* Such interdependency may be managed in any way, so long as all of the
* descriptors complete by the time the composite driver returns from
* its bind() routine.
*/
struct usb_configuration {
const char *label;
struct usb_gadget_strings **strings;
const struct usb_descriptor_header **descriptors;
/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis. See if
* we can't restructure things to avoid mismatching...
*/
/* configuration management: unbind/setup */
void (*unbind)(struct usb_configuration *);
int (*setup)(struct usb_configuration *,
const struct usb_ctrlrequest *);
/* fields in the config descriptor */
u8 bConfigurationValue;
u8 iConfiguration;
u8 bmAttributes;
u16 MaxPower;
struct usb_composite_dev *cdev;
/* private: */
/* internals */
//_LIST list;
//_LIST function_lists;
dwc_list_link_t list;
dwc_list_link_t function_lists; // by jimmy
u8 next_interface_id;
unsigned superspeed:1;
unsigned highspeed:1;
unsigned fullspeed:1;
struct usb_function *interface[MAX_CONFIG_INTERFACES];
};
_LONG_CALL_ int usb_interface_id(struct usb_configuration *config,
struct usb_function *function);
_LONG_CALL_ int usb_add_config(struct usb_composite_dev *,
struct usb_configuration *,
int (*)(struct usb_configuration *));
_LONG_CALL_ void usb_remove_config(struct usb_composite_dev *,
struct usb_configuration *);
/**
* struct usb_function - describes one function of a configuration
* @name: For diagnostics, identifies the function.
* @strings: tables of strings, keyed by identifiers assigned during bind()
* and by language IDs provided in control requests
* @fs_descriptors: Table of full (or low) speed descriptors, using interface and
* string identifiers assigned during @bind(). If this pointer is null,
* the function will not be available at full speed (or at low speed).
* @hs_descriptors: Table of high speed descriptors, using interface and
* string identifiers assigned during @bind(). If this pointer is null,
* the function will not be available at high speed.
* @ss_descriptors: Table of super speed descriptors, using interface and
* string identifiers assigned during @bind(). If this
* pointer is null after initiation, the function will not
* be available at super speed.
* @config: assigned when @usb_add_function() is called; this is the
* configuration with which this function is associated.
* @os_desc_table: Table of (interface id, os descriptors) pairs. The function
* can expose more than one interface. If an interface is a member of
* an IAD, only the first interface of IAD has its entry in the table.
* @os_desc_n: Number of entries in os_desc_table
* @bind: Before the gadget can register, all of its functions bind() to the
* available resources including string and interface identifiers used
* in interface or class descriptors; endpoints; I/O buffers; and so on.
* @unbind: Reverses @bind; called as a side effect of unregistering the
* driver which added this function.
* @free_func: free the struct usb_function.
* @mod: (internal) points to the module that created this structure.
* @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may
* initialize usb_ep.driver data at this time (when it is used).
* Note that setting an interface to its current altsetting resets
* interface state, and that all interfaces have a disabled state.
* @get_alt: Returns the active altsetting. If this is not provided,
* then only altsetting zero is supported.
* @disable: (REQUIRED) Indicates the function should be disabled. Reasons
* include host resetting or reconfiguring the gadget, and disconnection.
* @setup: Used for interface-specific control requests.
* @suspend: Notifies functions when the host stops sending USB traffic.
* @resume: Notifies functions when the host restarts USB traffic.
* @get_status: Returns function status as a reply to
* GetStatus() request when the recipient is Interface.
* @func_suspend: callback to be called when
* SetFeature(FUNCTION_SUSPEND) is reseived
*
* A single USB function uses one or more interfaces, and should in most
* cases support operation at both full and high speeds. Each function is
* associated by @usb_add_function() with a one configuration; that function
* causes @bind() to be called so resources can be allocated as part of
* setting up a gadget driver. Those resources include endpoints, which
* should be allocated using @usb_ep_autoconfig().
*
* To support dual speed operation, a function driver provides descriptors
* for both high and full speed operation. Except in rare cases that don't
* involve bulk endpoints, each speed needs different endpoint descriptors.
*
* Function drivers choose their own strategies for managing instance data.
* The simplest strategy just declares it "static', which means the function
* can only be activated once. If the function needs to be exposed in more
* than one configuration at a given speed, it needs to support multiple
* usb_function structures (one for each configuration).
*
* A more complex strategy might encapsulate a @usb_function structure inside
* a driver-specific instance structure to allows multiple activations. An
* example of multiple activations might be a CDC ACM function that supports
* two or more distinct instances within the same configuration, providing
* several independent logical data links to a USB host.
*/
struct usb_function {
const char *name;
struct usb_gadget_strings **strings;
struct usb_descriptor_header **fs_descriptors;
struct usb_descriptor_header **hs_descriptors;
// struct usb_descriptor_header **ss_descriptors;
struct usb_configuration *config;
// struct usb_os_desc_table *os_desc_table;
// unsigned os_desc_n;
/* REVISIT: bind() functions can be marked __init, which
* makes trouble for section mismatch analysis. See if
* we can't restructure things to avoid mismatching.
* Related: unbind() may kfree() but bind() won't...
*/
/* configuration management: bind/unbind */
int (*bind)(struct usb_configuration *,
struct usb_function *);
void (*unbind)(struct usb_configuration *,
struct usb_function *);
void (*free_func)(struct usb_function *f);
struct module *mod;
/* runtime state management */
int (*set_alt)(struct usb_function *,
unsigned interface, unsigned alt);
int (*get_alt)(struct usb_function *,
unsigned interface);
void (*disable)(struct usb_function *);
int (*setup)(struct usb_function *,
const struct usb_ctrlrequest *);
void (*suspend)(struct usb_function *);
void (*resume)(struct usb_function *);
/* USB 3.0 additions */
int (*get_status)(struct usb_function *);
int (*func_suspend)(struct usb_function *,
u8 suspend_opt);
/* private: */
/* internals */
//_LIST list;
dwc_list_link_t list; // by jimmy
// DECLARE_BITMAP(endpoints, 32);
// const struct usb_function_instance *fi;
};
#endif
extern _LONG_CALL_ int usb_add_function(struct usb_configuration *, struct usb_function *);
extern _LONG_CALL_ void usb_remove_function(struct usb_configuration *, struct usb_function *);
extern _LONG_CALL_ void usb_put_function(struct usb_function *);
extern _LONG_CALL_ int usb_function_deactivate(struct usb_function *);
extern _LONG_CALL_ int usb_function_activate(struct usb_function *);
extern _LONG_CALL_ int usb_interface_id(struct usb_configuration *, struct usb_function *);
extern _LONG_CALL_ int usb_composite_probe(struct usb_composite_driver *driver);
extern _LONG_CALL_ int register_class_vendor_control_request_cb(struct usb_composite_dev *cdev, user_control_callback cb);
extern _LONG_CALL_ void usb_composite_unregister(struct usb_composite_driver *driver);
#endif

View File

@@ -0,0 +1,12 @@
#ifndef _USB_CONFIG_H_
#define _USB_CONFIG_H_
#include "core/inc/usb_composite.h"
extern _LONG_CALL_ int usb_assign_descriptors(struct usb_function *f,
struct usb_descriptor_header **fs,
struct usb_descriptor_header **hs,
struct usb_descriptor_header **ss);
extern _LONG_CALL_ void usb_free_all_descriptors(struct usb_function *f);
#endif