void usbRequestReceived(void) { uint8_t requestType = usbRequest.bmRequestType & 0x60; // reset the ep0 packetizer packetizer_data_ptr = 0; packetizer_data_size = 0; if (requestType == 0x00) // standard request { uint8_t recipient = usbRequest.bmRequestType & 0x1f; if (recipient == 0) // device usbStdDeviceRequest(); else if (recipient == 1) // interface usbStdInterfaceRequest(); else if (recipient == 2) // endpoint usbStdEndpointRequest(); else USB_EP0_STALL(); } else if (requestType == 0x20) { // class request usbHidRequest(); //} else if (requestType == 0x40) { // vendor request } else { // stall on unsupported requests USB_EP0_STALL(); } }
static void usb_process_get_descriptor() { packetizer_pkt_size = MAX_PACKET_SIZE_EP0; // Switch on descriptor type switch(setupbuf[3]) { case USB_DESC_DEVICE: packetizer_data_ptr = (uint8_t*)&g_usb_dev_desc; packetizer_data_size = MIN(setupbuf[6], sizeof(hal_usb_dev_desc_t)); packetizer_isr_ep0_in(); break; case USB_DESC_CONFIGURATION: // For now we just support one configuration. The asked configuration is stored in LSB(wValue). packetizer_data_ptr = (uint8_t*)&g_usb_conf_desc; packetizer_data_size = MIN(setupbuf[6], sizeof(usb_conf_desc_templ_t)); packetizer_isr_ep0_in(); break; case USB_DESC_STRING: // For now we just support english as string descriptor language. if(setupbuf[2] == 0x00) { packetizer_data_ptr = string_zero; packetizer_data_size = MIN(setupbuf[6], sizeof(string_zero)); packetizer_isr_ep0_in(); } else { if((setupbuf[2] - 1) < USB_STRING_DESC_COUNT) { if (setupbuf[2] == 1) packetizer_data_ptr = g_usb_string_desc_1; else packetizer_data_ptr = g_usb_string_desc_2;; packetizer_data_size = MIN(setupbuf[6], packetizer_data_ptr[0]); 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: USB_EP0_HSNAK(); break; } }
void usbHidRequest(void) { uint8_t bRequest = usbRequest.bRequest; if (bRequest == USB_REQ_HID_SET_REPORT) { // we get and process the actual data in usbRequestDataReceived() } else if (bRequest == USB_REQ_HID_GET_REPORT) { on_get_report(); } else if (bRequest == USB_REQ_HID_GET_IDLE) { in0buf[0] = usbHidIdle; in0bc = 0x01; } else if (bRequest == USB_REQ_HID_SET_IDLE) { usbHidIdle = usbRequest.wValueMSB; // wValueLSB holds the reportID for which this rate applies, // but we only have one, so this does not concern us usbFrameCnt = 0; // reset idle counter // send an empty packet and ACK the request in0bc = 0x00; USB_EP0_HSNAK(); } else { USB_EP0_STALL(); } }
static void usb_process_get_status() { IN0BUF[0] = 0; IN0BUF[1] = 0x00; if((usb_state == ADDRESSED) && (SETUPBUF[4] == 0x00)) { IN0BC = 0x02; } else if(usb_state == CONFIGURED) { switch(bmRequestType) { case 0x80: // Device if((usb_bm_state & USB_BM_STATE_ALLOW_REMOTE_WAKEUP ) == USB_BM_STATE_ALLOW_REMOTE_WAKEUP) { IN0BUF[0] = 0x02; } IN0BC = 0x02; break; case 0x81: // Interface IN0BC = 0x02; break; case 0x82: // Endpoint if((SETUPBUF[4] & 0x80) == 0x80) // IN endpoints IN0BUF[0] = IN1CS; else IN0BUF[0] = OUT1CS; IN0BC = 0x02; break; default: USB_EP0_STALL(); break; } } else { // We should not be in this state USB_EP0_STALL(); } }
static void usb_process_get_status() { in0buf[0] = in0buf[1] = 0x00; if((usb_state == ADDRESSED) && (setupbuf[4] == 0x00)) { in0bc = 0x02; } else if(usb_state == CONFIGURED) { switch(bmRequestType) { case 0x80: // Device if((usb_bm_state & USB_BM_STATE_ALLOW_REMOTE_WAKEUP ) == USB_BM_STATE_ALLOW_REMOTE_WAKEUP) { in0buf[0] = 0x02; } in0bc = 0x02; break; case 0x81: // Interface in0bc = 0x02; break; case 0x82: // Endpoint if((setupbuf[4] & 0x80) == 0x80) // IN endpoints in0buf[0] = in1cs; else in0buf[0] = out1cs; in0bc = 0x02; break; default: USB_EP0_STALL(); break; } } else { // We should not be in this state USB_EP0_STALL(); } }
void usbGetDescriptor(void) { uint8_t descriptor = usbReqGetDesc.descType; packetizer_data_ptr = 0; packetizer_data_size = 0; if (descriptor == USB_DESC_DEVICE) { packetizer_data_ptr = (__code uint8_t*) &usb_dev_desc; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, packetizer_data_ptr[0]); } else if (descriptor == USB_DESC_CONFIGURATION) { packetizer_data_ptr = (__code uint8_t*) &joystick_conf_desc; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, sizeof joystick_conf_desc); } else if (descriptor == USB_DESC_STRING) { uint8_t string_id = usbReqGetDesc.descIndex; // string index 0 is list of supported lang ids if (string_id < USB_STRING_DESC_COUNT) { if (usbReqGetDesc.descIndex == 0) packetizer_data_ptr = usb_string_desc_0; else if (string_id == 1) packetizer_data_ptr = (__code uint8_t*) usb_string_desc_1; else if (string_id == 2) packetizer_data_ptr = (__code uint8_t*) usb_string_desc_2; else packetizer_data_ptr = (__code uint8_t*) usb_string_desc_3; if (usbReqGetDesc.lengthMSB > 0) packetizer_data_size = 0xff; else packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, packetizer_data_ptr[0]); } } else if (descriptor == USB_DESC_HID_REPORT) { if (usbReqHidGetDesc.interface == 0) { packetizer_data_ptr = joystick_hid_report_descriptor; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, JOYSTICK_HID_REPORT_DESC_SIZE); } else { packetizer_data_ptr = mouse_hid_report_descriptor; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, MOUSE_HID_REPORT_DESC_SIZE); } } if (packetizer_data_ptr) packetizer_isr_ep0_in(); else USB_EP0_STALL(); }
void usbHidRequest(void) { uint8_t bRequest = usbRequest.bRequest; if (bRequest == USB_REQ_HID_SET_REPORT) { // we have to wait for the 1 byte LED report // which will come with the next EP0OUT interrupt } else if (bRequest == USB_REQ_HID_GET_REPORT) { // this requests the HID report we defined with the HID report descriptor. // this is usually sent over EP1 IN, but can be sent over EP0 too. in0buf[0] = kbdReport.modifiers; in0buf[1] = 0; in0buf[2] = kbdReport.keys[0]; in0buf[3] = kbdReport.keys[1]; in0buf[4] = kbdReport.keys[2]; in0buf[5] = kbdReport.keys[3]; in0buf[6] = kbdReport.keys[4]; in0buf[7] = kbdReport.keys[5]; // send the data on it's way in0bc = 8; } else if (bRequest == USB_REQ_HID_GET_IDLE) { in0buf[0] = usbHidIdle; in0bc = 0x01; } else if (bRequest == USB_REQ_HID_SET_IDLE) { usbHidIdle = usbRequest.wValueMSB; // wValueLSB holds the reportID for which this rate applies, // but we only have one, so this does not concern us usbFrameCnt = 0; // reset idle counter // send an empty packet and ACK the request in0bc = 0x00; USB_EP0_HSNAK(); } else { USB_EP0_STALL(); } }
void usbGetDescriptor(void) { uint8_t descriptor = usbReqGetDesc.descType; packetizer_data_ptr = 0; packetizer_data_size = 0; if (descriptor == USB_DESC_DEVICE) { packetizer_data_ptr = (__code uint8_t*) &usb_dev_desc; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, packetizer_data_ptr[0]); } else if (descriptor == USB_DESC_CONFIGURATION) { packetizer_data_ptr = (__code uint8_t*) &usb_conf_desc; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, sizeof usb_conf_desc); } else if (descriptor == USB_DESC_STRING) { uint8_t string_id = usbReqGetDesc.descIndex; // string index 0 is list of supported lang ids if (string_id < USB_STRING_DESC_COUNT) { if (usbReqGetDesc.descIndex == 0) packetizer_data_ptr = usb_string_desc_0; else if (string_id == 1) packetizer_data_ptr = (__code uint8_t*) usb_string_desc_1; else if (string_id == 2) packetizer_data_ptr = (__code uint8_t*) usb_string_desc_2; else packetizer_data_ptr = (__code uint8_t*) usb_string_desc_3; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, packetizer_data_ptr[0]); } } else if (descriptor == USB_DESC_HID_REPORT) { packetizer_data_ptr = usb_hid_report_descriptor; packetizer_data_size = MIN(usbReqGetDesc.lengthLSB, USB_HID_REPORT_DESCRIPTOR_SIZE); } if (packetizer_data_ptr) packetizer_isr_ep0_in(); else USB_EP0_STALL(); }
void usbStdInterfaceRequest(void) { uint8_t bRequest = usbRequest.bRequest; if (bRequest == USB_REQ_GET_STATUS) { if (usb_state == CONFIGURED) { // all values are reserved for interfaces in0buf[0] = 0x00; in0buf[1] = 0x00; in0bc = 0x02; } } else if (bRequest == USB_REQ_GET_DESCRIPTOR) { // this requests the HID report descriptor usbGetDescriptor(); } else { USB_EP0_STALL(); } }
void usbStdEndpointRequest(void) { if (usbRequest.bRequest == USB_REQ_GET_STATUS) { if (usb_state == CONFIGURED) { // return Halt feature status uint8_t endpoint = usbRequest.wIndexLSB; if (endpoint == 0x81) in0buf[0] = in1cs & 0x01; else if (endpoint == 0x82) in0buf[0] = in2cs & 0x01; else if (endpoint == 0x01) in0buf[0] = out1cs & 0x01; in0bc = 0x02; } } else { USB_EP0_STALL(); } }
void usbStdEndpointRequest(void) { if (usbRequest.bRequest == USB_REQ_GET_STATUS) { if (usb_state == CONFIGURED) { // return Halt feature status uint8_t endpoint = usbRequest.wIndexLSB; if (endpoint == 0x81) in0buf[0] = in1cs & 0x01; else if (endpoint == 0x01) in0buf[0] = out1cs & 0x01; in0bc = 0x02; } } else if (usbRequest.bRequest == USB_REQ_CLEAR_FEATURE || usbRequest.bRequest == USB_REQ_SET_FEATURE) { // send an empty packet and ACK the request in0bc = 0x00; USB_EP0_HSNAK(); } else { USB_EP0_STALL(); } }
void usbStdDeviceRequest(void) { switch (usbRequest.bRequest) { case USB_REQ_GET_STATUS: // We must be in ADDRESSED or CONFIGURED state, and wIndex must be 0 if ((usb_state == ADDRESSED || usb_state == CONFIGURED) && usbRequest.wIndexLSB == 0x00) { // We aren't self-powered and we don't support remote wakeup in0buf[0] = 0x00; in0buf[1] = 0x00; in0bc = 0x02; } else { // Stall for invalid requests USB_EP0_STALL(); } break; case USB_REQ_SET_ADDRESS: // USB controller takes care of setting our address usb_state = ADDRESSED; break; case USB_REQ_GET_DESCRIPTOR: usbGetDescriptor(); break; case USB_REQ_GET_CONFIGURATION: if (usb_state == ADDRESSED) { in0buf[0] = 0x00; in0bc = 0x01; } else if (usb_state == CONFIGURED) { in0buf[0] = usb_current_config; in0bc = 0x01; } else { // Behavior not specified in other states, so STALL USB_EP0_STALL(); } break; case USB_REQ_SET_CONFIGURATION: if (usbRequest.wValueLSB == 0x00) { usb_state = ADDRESSED; usb_current_config = 0x00; // Since there isn't a data stage for this request, // we have to explicitly clear the NAK bit USB_EP0_HSNAK(); } else if (usbRequest.wValueLSB == 0x01) { usb_state = CONFIGURED; usb_current_config = 0x01; // Since there isn't a data stage for this request, // we have to explicitly clear the NAK bit USB_EP0_HSNAK(); } else { // Stall for invalid config values USB_EP0_STALL(); } break; } }
static void isr_sudav() { packetizer_pkt_size = MAX_PACKET_SIZE_EP0; bmRequestType = SETUPBUF[0]; if((bmRequestType & 0x60 ) == 0x00) { switch(SETUPBUF[1]) { case USB_REQ_GET_DESCRIPTOR: usb_process_get_descriptor(); break; case USB_REQ_GET_STATUS: usb_process_get_status(); break; case USB_REQ_SET_ADDRESS: usb_state = ADDRESSED; usb_current_config = 0x00; break; case USB_REQ_GET_CONFIGURATION: switch(usb_state) { case ADDRESSED: IN0BUF[0] = 0x00; IN0BC = 0x01; break; case CONFIGURED: IN0BUF[0] = usb_current_config; IN0BC = 0x01; break; case ATTACHED: case POWERED: case SUSPENDED: case DEFAULT: default: USB_EP0_STALL(); break; } break; case USB_REQ_SET_CONFIGURATION: switch(SETUPBUF[2]) { case 0x00: usb_state = ADDRESSED; usb_current_config = 0x00; USB_EP0_HSNAK(); break; case 0x01: usb_state = CONFIGURED; usb_bm_state |= USB_BM_STATE_CONFIGURED; usb_current_config = 0x01; USB_EP0_HSNAK(); break; default: USB_EP0_STALL(); break; } break; case USB_REQ_GET_INTERFACE: // GET_INTERFACE IN0BUF[0] = usb_current_alt_interface; IN0BC = 0x01; break; case USB_REQ_SET_DESCRIPTOR: case USB_REQ_SET_INTERFACE: // SET_INTERFACE case USB_REQ_SYNCH_FRAME: // SYNCH_FRAME default: USB_EP0_STALL(); break; } } // bmRequestType = 0 01 xxxxx : Data transfer direction: Host-to-device, Type: Class else if((bmRequestType & 0x60 ) == 0x20) // Class request { bool cret = handle_class_request((usbRequest_t *) SETUPBUF); if (SETUPBUF[6] != 0 && ((bmRequestType & 0x80) == 0x00)) OUT0BC = 0xff; else if (!cret) USB_EP0_HSNAK(); } else // Unknown request type { USB_EP0_STALL(); } }
static void usb_process_get_descriptor() { FSR&=~(1<<3); switch(SETUPBUF[3]) { case USB_DESC_DEVICE: ep0_send_data((__xdata uint8_t *)&g_usb_dev_desc, sizeof(usb_dev_desc_t)); //send_ipage_descriptor(IPAGE_OFF_g_usb_dev_desc, IPAGE_LEN_g_usb_dev_desc); break; case USB_DESC_CONFIGURATION: ep0_send_data((__xdata uint8_t *)&g_usb_conf_desc, sizeof(usb_conf_desc_bootloader_t)); //send_ipage_descriptor(IPAGE_OFF_g_usb_conf_desc, IPAGE_LEN_g_usb_conf_desc); break; case USB_DESC_HID: ep0_send_data((__xdata uint8_t *)&g_usb_conf_desc.hid, sizeof(usb_hid_desc_t)); break; case USB_DESC_HID_REPORT: ep0_send_data((__xdata uint8_t *)&g_usb_hid_report_desc, USB_DESC_HID_LEN); break; case USB_DESC_STRING: if(SETUPBUF[2] == 0x00) { ep0_send_data((__xdata uint8_t *)string_zero, sizeof(string_zero)); } else { if((SETUPBUF[2] - 1) < USB_STRING_DESC_COUNT) { uint8_t *ptr; switch (SETUPBUF[2]) { case 1: ptr = g_usb_string_desc_1; break; case 2: ptr = g_usb_string_desc_2; break; case 3: ptr = g_usb_string_desc_3; break; } ep0_send_data((__xdata uint8_t *) ptr, ptr[0]); } 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: USB_EP0_HSNAK(); break; } }
static void isr_sudav() { bmRequestType = setupbuf[0]; if((bmRequestType & 0x60 ) == 0x00) { switch(setupbuf[1]) { case USB_REQ_GET_DESCRIPTOR: usb_process_get_descriptor(); break; case USB_REQ_GET_STATUS: usb_process_get_status(); break; case USB_REQ_SET_ADDRESS: usb_state = ADDRESSED; usb_current_config = 0x00; break; case USB_REQ_GET_CONFIGURATION: switch(usb_state) { case ADDRESSED: in0buf[0] = 0x00; in0bc = 0x01; break; case CONFIGURED: in0buf[0] = usb_current_config; in0bc = 0x01; break; case ATTACHED: case POWERED: case SUSPENDED: case DEFAULT: default: USB_EP0_STALL(); break; } break; case USB_REQ_SET_CONFIGURATION: switch(setupbuf[2]) { case 0x00: usb_state = ADDRESSED; usb_current_config = 0x00; USB_EP0_HSNAK(); break; case 0x01: usb_state = CONFIGURED; usb_bm_state |= USB_BM_STATE_CONFIGURED; usb_current_config = 0x01; USB_EP0_HSNAK(); break; default: USB_EP0_STALL(); break; } break; case USB_REQ_GET_INTERFACE: // GET_INTERFACE in0buf[0] = usb_current_alt_interface; in0bc = 0x01; break; case USB_REQ_SET_DESCRIPTOR: case USB_REQ_SET_INTERFACE: // SET_INTERFACE case USB_REQ_SYNCH_FRAME: // SYNCH_FRAME default: USB_EP0_STALL(); break; } } // bmRequestType = 0 01 xxxxx : Data transfer direction: Host-to-device, Type: Class else if((bmRequestType & 0x60 ) == 0x20) // Class request { if(setupbuf[6] != 0 && ((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. out0bc = 0xff; } else { USB_EP0_HSNAK(); } } else // Unknown request type { USB_EP0_STALL(); } }