fomu-factory-test/sw/src/usb-setup.c

138 lines
3.4 KiB
C

#include <stdint.h>
#include <unistd.h>
#include <usb.h>
#include <usb-desc.h>
#include <usb-cdc.h>
static uint8_t reply_buffer[8];
static uint8_t usb_configuration = 0;
int usb_setup(const struct usb_setup_request *setup)
{
const uint8_t *data = NULL;
uint32_t datalen = 0;
const usb_descriptor_list_t *list;
uint32_t max_length = setup->wLength;//((setup->wLength >> 8) & 0xff) | ((setup->wLength << 8) & 0xff00);
switch (setup->wRequestAndType)
{
// case 0x21a1: // Get Line Coding
// reply_buffer[0] = 0x80;
// reply_buffer[1] = 0x25;
// reply_buffer[2] = 0x00;
// reply_buffer[3] = 0x00;
// reply_buffer[4] = 0x00;
// reply_buffer[5] = 0x00;
// reply_buffer[6] = 0x08;
// data = reply_buffer;
// datalen = 7;
// break;
case 0x2021: // Set Line Coding
case 0x20A1: // Set Line Coding
break;
case 0x2221: // Set control line state
cdc_set_connected(setup->wValue & 1); /* Check RTS bit */
break;
case 0x0500: // SET_ADDRESS
case 0x0b01: // SET_INTERFACE
break;
case 0x0900: // SET_CONFIGURATION
usb_configuration = setup->wValue;
break;
case 0x0880: // GET_CONFIGURATION
reply_buffer[0] = usb_configuration;
datalen = 1;
data = reply_buffer;
break;
case 0x0080: // GET_STATUS (device)
reply_buffer[0] = 0;
reply_buffer[1] = 0;
datalen = 2;
data = reply_buffer;
break;
case 0x0082: // GET_STATUS (endpoint)
if (setup->wIndex > 0)
{
usb_err();
return 0;
}
reply_buffer[0] = 0;
reply_buffer[1] = 0;
// XXX handle endpoint stall here
data = reply_buffer;
datalen = 2;
break;
case 0x0102: // CLEAR_FEATURE (endpoint)
if (setup->wIndex > 0 || setup->wValue != 0)
{
// TODO: do we need to handle IN vs OUT here?
usb_err();
return 0;
}
break;
case 0x0302: // SET_FEATURE (endpoint)
if (setup->wIndex > 0 || setup->wValue != 0)
{
// TODO: do we need to handle IN vs OUT here?
usb_err();
return 0;
}
// XXX: Should we set the stall bit?
// USB->DIEP0CTL |= USB_DIEP_CTL_STALL;
// TODO: do we need to clear the data toggle here?
break;
case 0x0680: // GET_DESCRIPTOR
case 0x0681:
for (list = usb_descriptor_list; 1; list++)
{
if (list->addr == NULL)
break;
if (setup->wValue == list->wValue)
{
data = list->addr;
if ((setup->wValue >> 8) == 3)
{
// for string descriptors, use the descriptor's
// length field, allowing runtime configured
// length.
datalen = *(list->addr);
}
else
{
datalen = list->length;
}
goto send;
}
}
usb_err();
return 0;
default:
usb_err();
return 0;
}
send:
if (data && datalen) {
if (datalen > max_length)
datalen = max_length;
usb_send(data, datalen);
}
else
usb_ack_in();
return 2;
}