/* Don't make this function static to avoid inlining. * The entire function would become too large and exceed the range of * relative jumps. * 2006-02-25: Either gcc 3.4.3 is better than the gcc used when the comment * above was written, or other parts of the code have changed. We now get * better results with an inlined function. Test condition: PowerSwitch code. */ static void usbProcessRx(uchar *data, uchar len) { usbRequest_t *rq = (void *)data; uchar replyLen = 0, flags = USB_FLG_USE_DEFAULT_RW; /* We use if() cascades because the compare is done byte-wise while switch() * is int-based. The if() cascades are therefore more efficient. */ DBG2(0x10 + ((usbRxToken >> 6) & 3), data, len); #if USB_CFG_IMPLEMENT_FN_WRITEOUT if(usbRxToken & 0x80){ usbFunctionWriteOut(data, len); return; /* no reply expected, hence no usbMsgPtr, usbMsgFlags, usbMsgLen set */ } if(usbRxToken == (uchar)(USBPID_SETUP & 0x7f)){ /* MSb contains endpoint (== 0) */ #else if(usbRxToken == (uchar)USBPID_SETUP){ #endif if(len == 8){ /* Setup size must be always 8 bytes. Ignore otherwise. */ uchar type = rq->bmRequestType & USBRQ_TYPE_MASK; if(type == USBRQ_TYPE_STANDARD){ #define SET_REPLY_LEN(len) replyLen = (len); usbMsgPtr = replyData /* This macro ensures that replyLen and usbMsgPtr are always set in the same way. * That allows optimization of common code in if() branches */ uchar *replyData = usbTxBuf + 9; /* there is 3 bytes free space at the end of the buffer */ replyData[0] = 0; /* common to USBRQ_GET_STATUS and USBRQ_GET_INTERFACE */ if(rq->bRequest == USBRQ_GET_STATUS){ /* 0 */ uchar __attribute__((__unused__)) recipient = rq->bmRequestType & USBRQ_RCPT_MASK; /* assign arith ops to variables to enforce byte size */ #if USB_CFG_IS_SELF_POWERED if(recipient == USBRQ_RCPT_DEVICE) replyData[0] = USB_CFG_IS_SELF_POWERED; #endif #if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_IMPLEMENT_HALT if(recipient == USBRQ_RCPT_ENDPOINT && rq->wIndex.bytes[0] == 0x81) /* request status for endpoint 1 */ replyData[0] = usbTxLen1 == USBPID_STALL; #endif replyData[1] = 0; SET_REPLY_LEN(2); }else if(rq->bRequest == USBRQ_SET_ADDRESS){ /* 5 */ usbNewDeviceAddr = rq->wValue.bytes[0]; }else if(rq->bRequest == USBRQ_GET_DESCRIPTOR){ /* 6 */ flags = USB_FLG_MSGPTR_IS_ROM | USB_FLG_USE_DEFAULT_RW; if(rq->wValue.bytes[1] == USBDESCR_DEVICE){ /* 1 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_DEVICE, usbDescriptorDevice) }else if(rq->wValue.bytes[1] == USBDESCR_CONFIG){ /* 2 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_CONFIGURATION, usbDescriptorConfiguration) }else if(rq->wValue.bytes[1] == USBDESCR_STRING){ /* 3 */ #if USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC if(USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_RAM) flags &= ~USB_FLG_MSGPTR_IS_ROM; replyLen = usbFunctionDescriptor(rq); #else /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ if(rq->wValue.bytes[0] == 0){ /* descriptor index */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_0, usbDescriptorString0) }else if(rq->wValue.bytes[0] == 1){ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_VENDOR, usbDescriptorStringVendor) }else if(rq->wValue.bytes[0] == 2){ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_DEVICE, usbDescriptorStringDevice) }else if(rq->wValue.bytes[0] == 3){ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber) }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ replyLen = usbFunctionDescriptor(rq); } #endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ }else if(rq->wValue.bytes[1] == USBDESCR_HID){ /* 0x21 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18) }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){ /* 0x22 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport) }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ replyLen = usbFunctionDescriptor(rq); } }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){ /* 8 */
}else if(rq->wValue.bytes[0] == 2){ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_PRODUCT, usbDescriptorStringDevice) }else if(rq->wValue.bytes[0] == 3){ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER, usbDescriptorStringSerialNumber) }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ replyLen = usbFunctionDescriptor(rq); } #endif /* USB_CFG_DESCR_PROPS_STRINGS & USB_PROP_IS_DYNAMIC */ #if USB_CFG_DESCR_PROPS_HID_REPORT /* only support HID descriptors if enabled */ }else if(rq->wValue.bytes[1] == USBDESCR_HID){ /* 0x21 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID, usbDescriptorConfiguration + 18) }else if(rq->wValue.bytes[1] == USBDESCR_HID_REPORT){ /* 0x22 */ GET_DESCRIPTOR(USB_CFG_DESCR_PROPS_HID_REPORT, usbDescriptorHidReport) #endif /* USB_CFG_DESCR_PROPS_HID_REPORT */ }else if(USB_CFG_DESCR_PROPS_UNKNOWN & USB_PROP_IS_DYNAMIC){ replyLen = usbFunctionDescriptor(rq); } }else if(rq->bRequest == USBRQ_GET_CONFIGURATION){ /* 8 */ replyData = &usbConfiguration; /* send current configuration value */ SET_REPLY_LEN(1); }else if(rq->bRequest == USBRQ_SET_CONFIGURATION){ /* 9 */ usbConfiguration = rq->wValue.bytes[0]; #if USB_CFG_IMPLEMENT_HALT usbTxLen1 = USBPID_NAK; #endif }else if(rq->bRequest == USBRQ_GET_INTERFACE){ /* 10 */ SET_REPLY_LEN(1); #if USB_CFG_HAVE_INTRIN_ENDPOINT }else if(rq->bRequest == USBRQ_SET_INTERFACE){ /* 11 */ USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */ # if USB_CFG_HAVE_INTRIN_ENDPOINT3