in src/cdc_enumerate.c [755:1055]
void AT91F_CDC_Enumerate() {
uint8_t bmRequestType, bRequest, dir;
uint16_t wValue, wIndex, wStatus;
/* Clear the Received Setup flag */
USB->DEVICE.DeviceEndpoint[0].EPINTFLAG.reg = USB_DEVICE_EPINTFLAG_RXSTP;
/* Read the USB request parameters */
bmRequestType = ctrlOutCache.buf[0];
bRequest = ctrlOutCache.buf[1];
wValue = (ctrlOutCache.buf[2] & 0xFF);
wValue |= (ctrlOutCache.buf[3] << 8);
wIndex = (ctrlOutCache.buf[4] & 0xFF);
wIndex |= (ctrlOutCache.buf[5] << 8);
wLength = (ctrlOutCache.buf[6] & 0xFF);
wLength |= (ctrlOutCache.buf[7] << 8);
/* Clear the Bank 0 ready flag on Control OUT */
USB->DEVICE.DeviceEndpoint[0].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK0RDY;
uint32_t reqId = (bRequest << 8) | bmRequestType;
logwrite("USBReq: ");
logwritenum(reqId);
logwrite(" wValue: ");
logwritenum(wValue);
logwrite(" wIndex: ");
logwritenum(wIndex);
logval(" wLen", wLength);
/* Handle supported standard device request Cf Table 9-3 in USB
* specification Rev 1.1 */
switch (reqId) {
case STD_GET_DESCRIPTOR1:
case STD_GET_DESCRIPTOR:
if (wValue == 0x100)
/* Return Device Descriptor */
sendCtrl(devDescriptor, sizeof(devDescriptor));
else if (wValue == 0x200)
/* Return Configuration Descriptor */
sendCtrl(cfgDescriptor, sizeof(cfgDescriptor));
else if (ctrlOutCache.buf[3] == 3) {
if (ctrlOutCache.buf[2] >= STRING_DESCRIPTOR_COUNT)
{
stall_ep(0);
} else {
StringDescriptor desc = {0};
desc.type = 3;
if (ctrlOutCache.buf[2] == 0) {
desc.len = 4;
desc.data[0] = 0x09;
desc.data[1] = 0x04;
} else {
load_serial_number(serial_number);
const char *ptr = string_descriptors[ctrlOutCache.buf[2]];
desc.len = strlen(ptr) * 2 + 2;
for (int i = 0; ptr[i]; i++) {
desc.data[i * 2] = ptr[i];
}
}
sendCtrl(&desc, desc.len);
}
} else if (ctrlOutCache.buf[3] == 0x0F) {
sendCtrl(bosDescriptor, sizeof(bosDescriptor));
}
#if USE_HID
else if (ctrlOutCache.buf[3] == 0x21) {
sendCtrl(hidCfgDescriptor, sizeof(hidCfgDescriptor));
} else if (ctrlOutCache.buf[3] == 0x22) {
sendCtrl(hidDescriptor, sizeof(hidDescriptor));
}
#endif
else {
/* Stall the request */
stall_ep(0);
}
break;
#if USE_WEBUSB
case STD_VENDOR_CTRL1:
stall_ep(0);
break;
case STD_VENDOR_CTRL2:
if (wIndex == 0x07)
sendCtrl(msOS20Descriptor, sizeof(msOS20Descriptor));
else
stall_ep(0);
break;
#endif
case STD_SET_ADDRESS:
/* Send ZLP */
AT91F_USB_SendZlp();
/* Set device address to the newly received address from host */
USB->DEVICE.DADD.reg = USB_DEVICE_DADD_ADDEN | wValue;
break;
case STD_SET_CONFIGURATION:
/* Store configuration */
currentConfiguration = (uint8_t)wValue;
/* Send ZLP */
AT91F_USB_SendZlp();
#if USE_CDC
configureInOut(USB_EP_IN);
/* Configure INTERRUPT IN endpoint for CDC COMM interface*/
USB->DEVICE.DeviceEndpoint[USB_EP_COMM].EPCFG.reg = USB_DEVICE_EPCFG_EPTYPE1(4);
/* Set maximum packet size as 64 bytes */
usb_endpoint_table[USB_EP_COMM].DeviceDescBank[1].PCKSIZE.bit.SIZE = 0;
USB->DEVICE.DeviceEndpoint[USB_EP_COMM].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
#endif
configureInOut(USB_EP_MSC_IN);
#if USE_HID
/* Configure INTERRUPT IN/OUT endpoint for HID interface*/
USB->DEVICE.DeviceEndpoint[USB_EP_HID].EPCFG.reg =
USB_DEVICE_EPCFG_EPTYPE0(4) | USB_DEVICE_EPCFG_EPTYPE1(4);
USB->DEVICE.DeviceEndpoint[USB_EP_HID].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
USB->DEVICE.DeviceEndpoint[USB_EP_HID].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
usb_endpoint_table[USB_EP_HID].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
usb_endpoint_table[USB_EP_HID].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
#endif
#if USE_WEBUSB
/* Configure INTERRUPT IN/OUT endpoint for HID interface*/
USB->DEVICE.DeviceEndpoint[USB_EP_WEB].EPCFG.reg =
USB_DEVICE_EPCFG_EPTYPE0(4) | USB_DEVICE_EPCFG_EPTYPE1(4);
USB->DEVICE.DeviceEndpoint[USB_EP_WEB].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSSET_BK0RDY;
USB->DEVICE.DeviceEndpoint[USB_EP_WEB].EPSTATUSCLR.reg = USB_DEVICE_EPSTATUSCLR_BK1RDY;
usb_endpoint_table[USB_EP_WEB].DeviceDescBank[0].PCKSIZE.bit.SIZE = 3;
usb_endpoint_table[USB_EP_WEB].DeviceDescBank[1].PCKSIZE.bit.SIZE = 3;
#endif
break;
case STD_GET_CONFIGURATION:
/* Return current configuration value */
sendCtrl(&(currentConfiguration), sizeof(currentConfiguration));
break;
case STD_GET_STATUS_ZERO:
wStatus = 0;
sendCtrl(&wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_INTERFACE:
wStatus = 0;
sendCtrl(&wStatus, sizeof(wStatus));
break;
case STD_GET_STATUS_ENDPOINT:
wStatus = 0;
dir = wIndex & 80;
wIndex &= 0x0F;
if (wIndex < MAX_EP) {
if (dir) {
wStatus = (USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg &
USB_DEVICE_EPSTATUSSET_STALLRQ1)
? 1
: 0;
} else {
wStatus = (USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg &
USB_DEVICE_EPSTATUSSET_STALLRQ0)
? 1
: 0;
}
/* Return current status of endpoint */
sendCtrl(&wStatus, sizeof(wStatus));
} else
/* Stall the request */
stall_ep(0);
break;
case STD_SET_FEATURE_ZERO:
/* Stall the request */
stall_ep(0);
break;
case STD_SET_FEATURE_INTERFACE:
/* Send ZLP */
AT91F_USB_SendZlp();
break;
case STD_SET_FEATURE_ENDPOINT:
dir = wIndex & 0x80;
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex < MAX_EP)) {
/* Set STALL request for the endpoint */
if (dir) {
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg =
USB_DEVICE_EPSTATUSSET_STALLRQ1;
} else {
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSSET.reg =
USB_DEVICE_EPSTATUSSET_STALLRQ0;
}
/* Send ZLP */
AT91F_USB_SendZlp();
} else
/* Stall the request */
stall_ep(0);
break;
case STD_CLEAR_FEATURE_ZERO:
/* Stall the request */
stall_ep(0);
break;
case STD_CLEAR_FEATURE_INTERFACE:
/* Send ZLP */
AT91F_USB_SendZlp();
break;
case STD_CLEAR_FEATURE_ENDPOINT:
dir = wIndex & 0x80;
wIndex &= 0x0F;
if ((wValue == 0) && wIndex && (wIndex < MAX_EP)) {
if (dir) {
if (USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg &
USB_DEVICE_EPSTATUSSET_STALLRQ1) {
// Remove stall request
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg =
USB_DEVICE_EPSTATUSCLR_STALLRQ1;
if (USB->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg &
USB_DEVICE_EPINTFLAG_STALL1) {
USB->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg =
USB_DEVICE_EPINTFLAG_STALL1;
// The Stall has occurred, then reset data toggle
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg =
USB_DEVICE_EPSTATUSSET_DTGLIN;
}
}
} else {
if (USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUS.reg &
USB_DEVICE_EPSTATUSSET_STALLRQ0) {
// Remove stall request
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg =
USB_DEVICE_EPSTATUSCLR_STALLRQ0;
if (USB->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg &
USB_DEVICE_EPINTFLAG_STALL0) {
USB->DEVICE.DeviceEndpoint[wIndex].EPINTFLAG.reg =
USB_DEVICE_EPINTFLAG_STALL0;
// The Stall has occurred, then reset data toggle
USB->DEVICE.DeviceEndpoint[wIndex].EPSTATUSCLR.reg =
USB_DEVICE_EPSTATUSSET_DTGLOUT;
}
}
}
/* Send ZLP */
AT91F_USB_SendZlp();
} else {
stall_ep(0);
}
break;
#if USE_CDC
// handle CDC class requests
case SET_LINE_CODING:
/* Send ZLP */
AT91F_USB_SendZlp();
break;
case GET_LINE_CODING:
/* Send current line coding */
sendCtrl(&line_coding, sizeof(usb_cdc_line_coding_t));
break;
case SET_CONTROL_LINE_STATE:
/* Store the current connection */
pCdc.currentConnection = wValue;
/* Send ZLP */
AT91F_USB_SendZlp();
break;
#endif
#if USE_MSC_CHECKS
// MSC
case MSC_RESET:
DBG_MSC(logmsg("MSC reset"));
msc_reset();
break;
#endif
case MSC_GET_MAX_LUN:
DBG_MSC(logmsg("MSC maxlun"));
wStatus = MAX_LUN;
sendCtrl(&wStatus, 1);
break;
#if USE_HID
case HID_REQUEST_GET_PROTOCOL:
case HID_REQUEST_GET_IDLE:
case HID_REQUEST_GET_REPORT: {
uint8_t buf[8] = {0};
sendCtrl(buf, 8);
} break;
case HID_REQUEST_SET_IDLE:
case HID_REQUEST_SET_REPORT:
case HID_REQUEST_SET_PROTOCOL:
AT91F_USB_SendZlp();
break;
#endif
default:
logval("Invalid CTRL command", reqId);
/* Stall the request */
stall_ep(0);
break;
}
}