?? hal_usb.c
字號:
if( LSB(req->wValue) == 0x00 )
{
packetize(g_hal_usb.descs.string_zero,
MIN(LSB(req->wLength), sizeof(g_hal_usb.descs.string_zero)),
g_hal_usb.descs.dev->bMaxPacketSize0);
packetizer_isr_ep0_in();
}
else
{
if( ( LSB(req->wValue) - 1 ) < USB_STRING_DESC_COUNT )
{
packetize((uint8_t*)(g_hal_usb.descs.string->idx[LSB(req->wValue)-1]),
MIN(LSB(req->wLength), g_hal_usb.descs.string->idx[LSB(req->wValue)-1][0]),
g_hal_usb.descs.dev->bMaxPacketSize0);
packetizer_isr_ep0_in();
}
else
{
USB_EP0_STALL();
}
}
break;
case USB_DESC_INTERFACE:
case USB_DESC_ENDPOINT:
case USB_DESC_DEVICE_QUAL:
case USB_DESC_OTHER_SPEED_CONF:
case USB_DESC_INTERFACE_POWER:
USB_EP0_STALL();
break;
default:
ret = g_hal_usb.device_req(req, &data_ptr, &data_size);
usb_process_dev_req_cb_response(ret, req, data_ptr, data_size);
break;
}
}
static void isr_sudav()
{
// Parse data in setupbuf
hal_usb_dev_req_resp_t ret;
uint8_t *data_ptr;
uint16_t data_size;
// Parsing the request into request structure
req.bmRequestType = i_usb.map->setupbuf[0];
req.bRequest = i_usb.map->setupbuf[1];
req.wValue = i_usb.map->setupbuf[2] + (i_usb.map->setupbuf[3] << 8);
req.wIndex = i_usb.map->setupbuf[4] + (i_usb.map->setupbuf[5] << 8);
req.wLength = i_usb.map->setupbuf[6] + (i_usb.map->setupbuf[7] << 8);
req.wLength = req.wLength > 0xff ? 0xff : LSB(req.wLength); // We truncate packets requests longer then 255 bytes
#if 0
uart0_putstring("\r\n--\r\nbmRequestType: "); hex_out_byte(req.bmRequestType);
uart0_putstring("\r\nbRequest : "); hex_out_byte(req.bRequest);
uart0_putstring("\r\nwValue [H][L]: "); hex_out_byte(MSB(req.wValue)); hex_out_byte(LSB(req.wValue));
uart0_putstring("\r\nwIndex [H][L]: "); hex_out_byte(MSB(req.wIndex)); hex_out_byte(LSB(req.wIndex));
uart0_putstring("\r\nwLength[H][L]: "); hex_out_byte(MSB(req.wLength)); hex_out_byte(LSB(req.wLength));
#endif
// bmRequestType = 0 00 xxxxx : Data transfer direction: Host-to-device Type: Standard
if( ( req.bmRequestType & 0x60 ) == 0x00 )
{
switch(req.bRequest)
{
case USB_REQ_GET_DESCRIPTOR:
usb_process_get_descriptor(&req);
break;
case USB_REQ_GET_STATUS:
usb_process_get_status(&req);
break; // case USB_REQ_GET_STATUS --end--
case USB_REQ_CLEAR_FEATURE:
switch(req.bmRequestType)
{
case 0x00: // Device
if( LSB(req.wValue) == USB_DEVICE_REMOTE_WAKEUP )
{
g_hal_usb.bm_state &= ~(USB_BM_STATE_ALLOW_REMOTE_WAKEUP);
USB_EP0_HSNAK();
}
else USB_EP0_STALL();
break;
case 0x01: // Interface
USB_EP0_STALL();
break;
case 0x02: // Endpoint
if( LSB(req.wValue) == USB_ENDPOINT_HALT )
{
hal_usb_endpoint_stall(LSB(req.wIndex), false);
USB_EP0_HSNAK();
}
else USB_EP0_STALL();
break;
default:
USB_EP0_STALL();
break;
}
break;
case USB_REQ_SET_FEATURE:
switch(req.bmRequestType)
{
case 0x00: // Device
if( LSB(req.wValue) == USB_DEVICE_REMOTE_WAKEUP )
{
g_hal_usb.bm_state |= USB_BM_STATE_ALLOW_REMOTE_WAKEUP;
USB_EP0_HSNAK();
}
else USB_EP0_STALL();
break;
case 0x01: // Interface
USB_EP0_STALL();
break;
case 0x02: // Endpoint - TODO: check for valid endpoints here
if( LSB(req.wValue) == USB_ENDPOINT_HALT )
{
hal_usb_endpoint_stall(LSB(req.wIndex), true);
USB_EP0_HSNAK();
}
else
{
USB_EP0_STALL();
}
break;
default:
USB_EP0_STALL();
break;
}
break;
case USB_REQ_SET_ADDRESS:
g_hal_usb.state = ADDRESSED;
g_hal_usb.current_config = 0x00;
break;
case USB_REQ_SET_DESCRIPTOR:
USB_EP0_STALL();
break;
case USB_REQ_GET_CONFIGURATION:
switch( g_hal_usb.state )
{
case ADDRESSED:
i_usb.map->in0buf[0] = 0x00;
i_usb.map->in0bc = 0x01;
break;
case CONFIGURED:
i_usb.map->in0buf[0] = g_hal_usb.current_config;
i_usb.map->in0bc = 0x01;
break;
default:
USB_EP0_STALL();
break;
}
break;
case USB_REQ_SET_CONFIGURATION:
switch(LSB(req.wValue)) {
case 0x00:
g_hal_usb.state = ADDRESSED;
g_hal_usb.current_config = 0x00;
USB_EP0_HSNAK();
break;
case 0x01:
g_hal_usb.state = CONFIGURED;
g_hal_usb.bm_state |= USB_BM_STATE_CONFIGURED;
g_hal_usb.current_config = 0x01;
USB_EP0_HSNAK();
break;
default:
USB_EP0_STALL();
break;
}
break;
case USB_REQ_GET_INTERFACE: // GET_INTERFACE
i_usb.map->in0buf[0] = g_hal_usb.current_alt_interface;
i_usb.map->in0bc = 0x01;
break;
case USB_REQ_SET_INTERFACE: // SET_INTERFACE
case USB_REQ_SYNCH_FRAME: // SYNCH_FRAME
USB_EP0_STALL(); // We do not support any of these
break;
default:
USB_EP0_STALL();
break;
};
}
// bmRequestType = 0 01 xxxxx : Data transfer direction: Host-to-device, Type: Class
else if( ( req.bmRequestType & 0x60 ) == 0x20 ) // Class request
{
if( req.wLength != 0 && ((req.bmRequestType & 0x80) == 0x00) )
{
// If there is a OUT-transaction associated with the Control-Transfer-Write we call the callback
// when the OUT-transaction is finished. Note that this function do not handle several out transactions.
i_usb.map->out0bc = 0xff;
}
else
{
ret = g_hal_usb.device_req(&req, &data_ptr, &data_size);
usb_process_dev_req_cb_response(ret, &req, data_ptr, data_size);
}
// Call the callback function. Data to be sent back to the host is store by the callback in data_ptr and the size in data_size.
}
else // Unknown request type
{
USB_EP0_STALL();
}
}
static void isr_sof()
{
}
static void isr_sutok()
{
i_usb.packetizer.data_ptr = NULL;
i_usb.packetizer.data_size = 0;
i_usb.packetizer.pkt_size = 0;
}
static void isr_suspend()
{
uint8_t allow_remote_wu = 0;
g_hal_usb.bm_state &= ~(USB_BM_STATE_HOST_WU); // We clear the flag that indicates that the host awoke the MCU via USB here
if( g_hal_usb.state == CONFIGURED )
{
if( ( g_hal_usb.bm_state & USB_BM_STATE_ALLOW_REMOTE_WAKEUP ) == USB_BM_STATE_ALLOW_REMOTE_WAKEUP )
{
allow_remote_wu = 1;
}
}
g_hal_usb.state = SUSPENDED;
if( g_hal_usb.suspend != NULL )
{
g_hal_usb.suspend(allow_remote_wu);
}
}
static void isr_usbreset()
{
g_hal_usb.state = DEFAULT;
g_hal_usb.current_config = 0;
g_hal_usb.current_alt_interface = 0;
g_hal_usb.bm_state = 0;
if( g_hal_usb.reset != NULL ) g_hal_usb.reset();
}
// For now we only support one out-transaction in a Control Transfer Write
static void isr_ep0out()
{
hal_usb_dev_req_resp_t ret;
uint8_t* data_ptr;
uint16_t data_size;
i_usb.packetizer.data_size = 0;
req.misc_data = i_usb.map->out0buf;
ret = g_hal_usb.device_req(&req, &data_ptr, &data_size);
usb_process_dev_req_cb_response(ret, &req, data_ptr, data_size);
}
//lint --e{528} suppress "usb_wu() not referenced"
void usb_wu(void) interrupt USB_WU // address: 0x005b
{
#define ICH4
#ifdef ICH4
uint8_t t;
#endif
// Check if the wakeup source is the pin to the USB controller
// If it is by the pin to the USB controller we want to start
// a remote wakeup
if( ( i_usb.map->usbcs & 0x80 ) == 0x80 )
{
// Reset the wakesrc indicator
i_usb.map->usbcs = 0x80;
// If we are allowed to perform a remote wakeup do that
if( ( g_hal_usb.bm_state & USB_BM_STATE_ALLOW_REMOTE_WAKEUP ) == USB_BM_STATE_ALLOW_REMOTE_WAKEUP )
{
#ifdef ICH4
// Force the J state on the USB lines
i_usb.map->usbcs |= 0x02;
// Typical 5.4us delay
_nop_();
_nop_();
t = i_usb.map->usbcs;
// Stop J state on the USB lines
t &= ~0x02;
// Signal remote resume
t |= 0x01;
// We have to set this register in one operation to avoid
// idle state is restored between the forced J and resume state
i_usb.map->usbcs = t;
#else
i_usb.map->usbcs |= 0x01; // Turn on the resume signal on the USB bus
#endif
delay_ms(7); //.1.7.7 Resume: The remote wakeup device must hold the resume signaling for at
// least 1 ms but for no more than 15ms
i_usb.map->usbcs &= ~0x01; // Turn off the resume signal on the USB bus
}
}
else
{
// We are awoken by the bus
g_hal_usb.bm_state |= USB_BM_STATE_HOST_WU;
}
if( ( g_hal_usb.bm_state & USB_BM_STATE_CONFIGURED ) == USB_BM_STATE_CONFIGURED )
{
g_hal_usb.state = CONFIGURED;
}
else
{
g_hal_usb.state = DEFAULT;
}
// Call resume callback
g_hal_usb.resume();
}
// This function processes the response from the EP callback
static void usb_process_ep_response(uint8_t ret, uint8_t* cs_ptr, uint8_t* bc_ptr)
{
if( ret == 0xff ) // Clear the OUTx busy flag enabling reception of the next OUT from USB-host
{
*bc_ptr = 0xff;
}
else if( ( ret & 0x80 ) == 0x80 ) // STALL
{
*cs_ptr = 0x01;
}
else if( ( ret & 0x60 ) == 0x60 ) // NAK
{
*cs_ptr = 0x02;
}
else if( ret == 0 ) // Zero length data
{
*bc_ptr = 0;
}
else
{
*bc_ptr = ret;
}
}
//lint --e{528} suppress "usb_irq(void) not referenced"
void usb_irq(void) interrupt USB_IRQ // address: 0x0063
{
uint8_t ep;
uint8_t ret;
xdata uint8_t *cs_ptr;
xdata uint8_t *buf_ptr;
xdata uint8_t *bc_ptr;
switch(i_usb.map->ivec)
{
case INT_SUDAV:
i_usb.map->usbirq = 0x01;
isr_sudav();
break;
case INT_SOF:
i_usb.map->usbirq = 0x02;
isr_sof();
break;
case INT_SUTOK:
i_usb.map->usbirq = 0x04;
isr_sutok();
break;
case INT_SUSPEND:
i_usb.map->usbirq = 0x08;
isr_suspend();
break;
case INT_USBRESET:
i_usb.map->usbirq = 0x10;
isr_usbreset();
break;
case INT_EP0IN:
i_usb.map->in_irq = 0x01;
packetizer_isr_ep0_in();
break;
case INT_EP0OUT:
i_usb.map->out_irq = 0x01;
isr_ep0out();
break;
case INT_EP1IN:
case INT_EP2IN:
case INT_EP3IN:
case INT_EP4IN:
case INT_EP5IN:
// Calculate IN endpoint number
ep = ( (i_usb.map->ivec) - INT_EP0IN ) / (INT_EP2IN - INT_EP1IN);
// Clear interrupt
i_usb.map->in_irq = ( 1 << ep );
cs_ptr = CALCULATE_CS_IN_PTR(ep);
buf_ptr = CALCULATE_BUF_IN_PTR(ep);
bc_ptr = CALCULATE_BC_IN_PTR(ep);
// Call registered callback
ret = i_usb.endpoint_in_isr[ep - 1](buf_ptr, bc_ptr);
usb_process_ep_response(ret, cs_ptr, bc_ptr);
break;
case INT_EP1OUT:
case INT_EP2OUT:
case INT_EP3OUT:
case INT_EP4OUT:
case INT_EP5OUT:
// Calculate OUT endpoint number
ep = ( (i_usb.map->ivec) - INT_EP0OUT) / (INT_EP2OUT - INT_EP1OUT);
// Clear interrupt
i_usb.map->out_irq = ( 1 << ep );
cs_ptr = CALCULATE_CS_OUT_PTR(ep);
buf_ptr = CALCULATE_BUF_OUT_PTR(ep);
bc_ptr = CALCULATE_BC_OUT_PTR(ep);
// Call registered callback
ret = (i_usb.endpoint_out_isr[ep - 1])(buf_ptr, bc_ptr);
usb_process_ep_response(ret, cs_ptr, bc_ptr);
break;
default:
break;
};
}
static void delay_ms(uint8_t ms)
{
uint16_t i, j;
for(i = 0; i < ms; i++ )
{
for( j = 0; j < 1403; j++) // 196
{
_nop_();
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -