?? usb.c
字號(hào):
const USB_vendor_device_desc_t usb_vendor_dev_desc =
{
sizeof(USB_vendor_device_desc_t),
USB_DEVICE_DESCRIPTOR,
0x0
};
/*=================================================================*
* String Descriptors *
*=================================================================*/
/*-------------------
* String descriptors
*------------------*/
const struct {
byte bLength;
byte bDescriptorType;
word bstring;
} langid_str_desc = {sizeof(langid_str_desc), STRING_DESCRIPTOR, ENGLISH_US};
const struct {
byte bLength;
byte bDescriptorType;
char bstring[sizeof(MANUFACTURER_STR)];
} manufacturer_str_desc = {sizeof(manufacturer_str_desc), STRING_DESCRIPTOR, MANUFACTURER_STR};
const struct {
byte bLength;
byte bDescriptorType;
char bstring[sizeof(PRODUCT_STR)];
} product_str_desc = {sizeof(product_str_desc), STRING_DESCRIPTOR, PRODUCT_STR};
const struct {
byte bLength;
byte bDescriptorType;
char bstring[sizeof(VERSION_STR)];
} version_str_desc = {sizeof(version_str_desc), STRING_DESCRIPTOR, VERSION_STR};
/*------------------------------------------------------
* List of all string descriptors, Be sure that the order
* of the list is the same as String_index_t enum
*------------------------------------------------------*/
const USB_string_desc_t *string_descs[] = {
(USB_string_desc_t*)&langid_str_desc,
(USB_string_desc_t*)&manufacturer_str_desc,
(USB_string_desc_t*)&product_str_desc,
(USB_string_desc_t*)&version_str_desc
};
void build_string_desc(USB_string_desc_t* dsc, byte* dsc_buff)
{
int i;
byte* dsc_buff_p;
dsc_buff[0] = dsc->bLength;
dsc_buff[1] = dsc->bDescriptorType;
/*-------------------------------
* make the string UNICODE encoded
* each char is two bytes long
*-------------------------------*/
dsc_buff_p = (byte *)(dsc_buff+2);
for(i=0;i<dsc->bLength; i++)
{
*dsc_buff_p++ = dsc->bstring[i];
*dsc_buff_p++ = 0x00;
}
}
/*=================================================================*
* Standard device request handlers *
*=================================================================*/
/*-------------------------------------------------------
* requests' sequence is according to USB 1.1 spec values
*-------------------------------------------------------*/
const USB_req_handler_t usb_std_device_req[] =
{
usb_dev_get_status,
usb_dev_clear_feature,
USB_req_reserved,
usb_dev_set_feature,
USB_req_reserved,
usb_dev_set_address,
usb_std_dev_get_descriptor,
usb_std_dev_set_descriptor,
usb_dev_get_config,
usb_dev_set_config,
usb_dev_get_interface,
usb_dev_set_interface,
usb_dev_sync_frame,
USB_req_reserved,
USB_req_reserved,
USB_req_reserved
};
/*=================================================================*
* Vendor device request handlers *
*=================================================================*/
const USB_req_handler_t usb_vendor_device_req[] =
{
Gen_Parser,
Bulk_Parser,
Interrupt_Parser,
Iso_Parser,
};
/*============================================================================
*
* Standard USB device request handlers
*
*============================================================================*/
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_dev_get_status(USB_request_t *req)
*
* Parameters
* req - pointer to struct of the received USB request
*
* Returns
* None
*
* Description
* Handles the GET_STATUS device request from the USB host.
*
* The GET_STATUS device request can go to one of three recipients: the device,
* the current interface, or a particular endpoint.
* 1. The device returns its self-powered status and its remote
* wake-up status.
* 2. The current interface returns, as defined in USB spec, 0.
* 3. The selected endpoint returns its stall status.
*
----------------------------------------------------------------------------------------------*/
void usb_dev_get_status(USB_request_t *req)
{
byte ep_no = REQ_INDEX(req).endpoint.ep_num;
if (DEVICE_STATE(device_status) == DEV_ATTACHED)
{
STALL_EP0();
return;
}
if (IS_REQ_VALUE_NOT_ZERO(req))
{
STALL_EP0();
return;
}
if (REQ_LENGTH(req) != 2)
{
STALL_EP0();
return;
}
/*-----------------------
* Clear all reserved bits
*-----------------------*/
device_buffers.status.msb.as_byte = 0;
switch (REQ_RECIPIENT(req))
{
case DEVICE_REQ:
if (REQ_INDEX(req).as_bytes.lsb != 0)
{
/*-------------------------------------
*device's behaviour is not specified
*------------------------------------*/
STALL_EP0();
return;
}
/*---------------------------------
*disable to request remote wakeup
*-------------------------------*/
device_buffers.status.msb.device.wakeup = OFF;
/*------------
*bus powered
*-----------*/
device_buffers.status.msb.device.selfpowered = OFF;
break;
case INTERFACE_REQ:
if (REQ_INDEX(req).interface.inf_no != 0)
{
/*------------------------------------
* device's behaviour is not specified
*------------------------------------*/
STALL_EP0();
return;
}
/*----------
* Reserved
*---------*/
device_buffers.status.msb.interface.value = 0;
break;
case ENDPOINT_REQ:
switch (ep_no)
{
case ENDPOINT_0:
device_buffers.status.msb.endpoint.stalled = (IS_EP0_STALLED)? ON : OFF;
break;
case ENDPOINT_1:
case ENDPOINT_2:
case ENDPOINT_3:
case ENDPOINT_4:
case ENDPOINT_5:
device_buffers.status.msb.endpoint.stalled = (IS_EP_STALLED(ep_no))? ON : OFF;
break;
/*----------------------
* endpoints not in use
*---------------------*/
case ENDPOINT_6:
default:
/*--------------------
* undefined endpoint
*--------------------*/
STALL_EP0();
return;
}
break;
case OTHER_REQ:
default:
/*---------------------
* undefined recipient
*-------------------*/
STALL_EP0();
return;
}
/*---------
* Reserved
*---------*/
device_buffers.status.lsb = 0;
send_control_data((byte *)&device_buffers.status, sizeof(USB_device_status_t));
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_dev_clear_feature(USB_request_t *req)
*
* Parameters
* req - pointer to struct of USB request
*
* Returns
* None
*
* Description
* Handles the CLEAR_FEATURE device request from the USB host.
*
* The CLEAR_FEATURE device request can go to one of two recipients:
* the device, or a particular endpoint.
* 1. The device returns a 0 length packet to complete the handshake with
* the host.
* 2. The selected endpoint only respond to clear stall commands.
*
----------------------------------------------------------------------------------------------*/
void usb_dev_clear_feature(USB_request_t *req)
{
byte ep_no = REQ_INDEX(req).endpoint.ep_num;
if (DEVICE_STATE(device_status) == DEV_ATTACHED)
{
STALL_EP0();
return;
}
if (REQ_LENGTH(req) != 0)
{
STALL_EP0();
return;
}
switch (REQ_RECIPIENT(req))
{
case DEVICE_REQ:
/*--------------------------------
* wakeup feature is not supported
*------------------------------*/
if (REQ_VALUE(req).feature.bSelector == DEVICE_REMOTE_WAKEUP)
STALL_EP0();
break;
case INTERFACE_REQ:
break;
case ENDPOINT_REQ:
/*-------------------------------------------
* clear stall state of appropriate endpoint
*-----------------------------------------*/
if (REQ_VALUE(req).feature.bSelector != ENDPOINT_STALL ||
ep_no >= ENDPOINT_LAST || usb_dev_endpoints[device_status.curAltSetting][ep_no] == NULL)
STALL_EP0();
else
{
(ep_no == ENDPOINT_0) ? CLEAR_STALL_EP0 : CLEAR_STALL_EP(ep_no);
zero_length_data_response(ENDPOINT_0);
}
break;
case OTHER_REQ:
default:
STALL_EP0();
break;
}
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_dev_set_feature(USB_request_t *req)
*
* Parameters
* req - pointer to struct of USB request
*
* Returns
* None
*
* Description
* Handles the SET_FEATURE device request from the USB host.
*
* The SET_FEATURE device request can go to one of two recipients:
* the device, or a particular endpoint.
* 1. The device responds to set remote wake-up commands
* 2. The selected endpoint responds to set stall commands.
*
----------------------------------------------------------------------------------------------*/
void usb_dev_set_feature(USB_request_t *req)
{
byte ep_no = REQ_INDEX(req).endpoint.ep_num;
if (DEVICE_STATE(device_status) == DEV_ATTACHED)
{
STALL_EP0();
return;
}
if (REQ_LENGTH(req) != 0)
{
STALL_EP0();
return;
}
switch (REQ_RECIPIENT(req))
{
case DEVICE_REQ:
if (REQ_VALUE(req).feature.bSelector == DEVICE_REMOTE_WAKEUP)
/*--------------------------------
* remote wakeup is not supported
*-------------------------------*/
STALL_EP0();
break;
case INTERFACE_REQ:
break;
case ENDPOINT_REQ:
if (REQ_VALUE(req).feature.bSelector != ENDPOINT_STALL ||
ep_no >= ENDPOINT_LAST || usb_dev_endpoints[device_status.curAltSetting][ep_no] == NULL)
STALL_EP0();
else
{
/*-----------------------------------------
* set appropriate endpoint to stall state
*---------------------------------------*/
(ep_no == ENDPOINT_0)? STALL_EP0() : STALL_EP(ep_no);
zero_length_data_response(ENDPOINT_0);
}
break;
case OTHER_REQ:
default:
STALL_EP0();
break;
}
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_dev_set_address(USB_request_t *req)
*
* Parameters
* req - pointer to struct of USB request
*
* Returns
* None
*
* Description
* Handles the SET_ADDRESS device request from the USB host.
----------------------------------------------------------------------------------------------*/
void usb_dev_set_address(USB_request_t *req)
{
byte address;
if (IS_REQ_INDEX_NOT_ZERO(req))
{
/*-----------------------------------------
* behavior of the device is not specified
*---------------------------------------*/
STALL_EP0();
return;
}
if (REQ_LENGTH(req) != 0x0)
{
/*----------------------------------------
* behavior of the device is not specified
*---------------------------------------*/
STALL_EP0();
return;
}
if (DEVICE_STATE(device_status) == DEV_CONFIGURED)
{
/*---------------------------------------
*behavior of the device is not specified
*--------------------------------------*/
STALL_EP0();
return;
}
switch (REQ_RECIPIENT(req))
{
case DEVICE_REQ:
/*------------------------
* ENABLE_DEFAULT_ADDRESS;
*-----------------------*/
write_usb(EPC0, read_usb(EPC0) | DEF);
/*-------------------------------------------------------
* The setting of device address is delayed in order to
* complete successfully the Status stage of this request
*------------------------------------------------------*/
address = REQ_VALUE(req).as_bytes.lsb;
/*-----------------------
* set new device address
*----------------------*/
write_usb(FAR, address|AD_EN);
/*---------------------------------
* Enable answer to the set address
*--------------------------------*/
if (REQ_VALUE(req).as_bytes.lsb == 0x0)
SET_DEVICE_STATE(device_status, DEV_ATTACHED);
else{
SET_DEVICE_STATE(device_status, DEV_ADDRESS);
/*------------------
* Set usb board leds
*------------------*/
SET_ID_LEDS(GET_DIP_SW1());
SET_USB_LED();
}
/*---------------------------------
* enable zero length data responce
*---------------------------------*/
usbn9604_tx_enable(ENDPOINT_0);
break;
case INTERFACE_REQ:
case ENDPOINT_REQ:
case OTHER_REQ:
default:
STALL_EP0();
break;
}
}
/*----------------------------------------------------------------------------------------------
* Prototype
* void usb_std_dev_get_descriptor(USB_request_t *req)
*
* Parameters
* req - pointer to struct of USB request
*
* Returns
* None
*
* Description
* Handles the standard GET_DESCRIPTOR device request from the USB host.
----------------------------------------------------------------------------------------------*/
void usb_std_dev_get_descriptor(USB_request_t *req)
{
int desc_length = 0;
int desc_index = REQ_VALUE(req).descriptor.bDescriptorIndex;
byte *desc_buf = NULL;
int max_desc_length = REQ_LENGTH(req);
switch (REQ_RECIPIENT(req))
{
case DEVICE_REQ:
switch (REQ_VALUE(req).descriptor.bDescriptorType)
{
case DEVICE_DESCRIPTOR:
desc_length = usb_device_desc.bLength;
desc_buf = (byte *)&usb_device_desc;
break;
case CONFIG_DESCRIPTOR:
desc_length = usb_dev_long_config_desc.usb_dev_config_desc.wTotalLength;
desc_buf = (byte *)&usb_dev_long_config_desc;
break;
case STRING_DESCRIPTOR:
/*---------------------------------------------------------------
* String index 0 for all languages returns an array of two-byte
* LANGID codes supported by the device
*-------------------------------------------------------------*/
if (desc_index < STR_LAST_INDEX && desc_index >= 0)
{
/*---------------------------------------------------------
* If the descriptor is longer than the wLength field,
* only the initial bytes of the descriptor are returned.
* If the descriptor is shorter than the wLength field,
* the device indicates the end of the control transfer
* by sending NULL character
*-----------------------------------------------------*/
desc_length = string_descs[desc_index]->bLength;
desc_buf = (byte *)string_descs[desc_index];
break;
}
/*-----------------------------------------------
* In case of the wrong string index, stall EP0
*---------------------------------------------*/
default:
STALL_EP0();
return;
}
desc_length = (desc_length < max_desc_length)? desc_length : max_desc_length;
if (desc_length%EP0_FIFO_SIZE)
/*-------------------------------------
* zero lada length will not be required
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -