static void packetizer_isr_ep0_in() { uint8_t code* data_ptr; uint8_t size, i; // We are getting a ep0in interupt when the host send ACK and do not have any more data to send if(packetizer_data_size == 0) { in0bc = 0; USB_EP0_HSNAK(); return; } size = MIN(packetizer_data_size, packetizer_pkt_size); // Copy data to the USB-controller buffer data_ptr = packetizer_data_ptr; for(i = 0; i < size;i++) { in0buf[i] = *data_ptr++; } // Tell the USB-controller how many bytes to send // If a IN is received from host after this the USB-controller will send the data in0bc = size; // Update the packetizer data packetizer_data_ptr += size; packetizer_data_size -= size; }
void packetizer_isr_ep0_in(void) { uint8_t size, i; if (packetizer_data_size == 0) { // We are getting a ep0in interrupt when the host sends ACK and do not have // any more data to send. Arm the in0bsy bit by writing to byte count reg in0bc = 0; // ACK the status stage USB_EP0_HSNAK(); return; } // Send the smallest of the data size and USB RAM EP0 IN size size = MIN(packetizer_data_size, USB_EP0_SIZE); // Copy data to the USB-controller buffer for (i = 0; i < size; ++i) in0buf[i] = *packetizer_data_ptr++; // Tell the USB-controller how many bytes to send // If a IN is received from host after this the USB-controller will send the data in0bc = size; // update the packetizer data count packetizer_data_size -= size; }
void usb_irq(void) { P0_4 = 1; // // Split case into an if and a switch to force Keil into not using a library function: if (ivec == INT_USBRESET) { usbirq = 0x10; usb_state = DEFAULT; usb_current_config = 0; usb_current_alt_interface = 0; usb_bm_state = 0; } else { switch(ivec) { case INT_SUDAV: usbirq = 0x01; isr_sudav(); break; case INT_SOF: usbirq = 0x02; break; case INT_SUTOK: usbirq = 0x04; packetizer_data_ptr = NULL; packetizer_data_size = 0; packetizer_pkt_size = 0; break; case INT_SUSPEND: usbirq = 0x08; break; case INT_EP0IN: in_irq = 0x01; packetizer_isr_ep0_in(); break; case INT_EP0OUT: out_irq = 0x01; packetizer_data_size = 0; // req.misc_data = out0buf; USB_EP0_HSNAK(); break; case INT_E21IN: // Clear interrupt in_irq = 0x04; break; case INT_EP2OUT: // Clear interrupt out_irq = 0x04; packet_received = true; out2bc = 0xff; break; default: break; } } P0_4 = 0; }
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(); } }
void usbRequestDataReceived(void) { if (usbRequest.bRequest == USB_REQ_HID_SET_REPORT) usbLEDReport = out0buf[0]; // send an empty packet and ACK the request in0bc = 0x00; USB_EP0_HSNAK(); }
void usbRequestDataReceived(void) { if (usbRequest.bRequest == USB_REQ_HID_SET_REPORT) on_set_report(); // size == usbReqHidGetSetReport.wLength // send an empty packet to ACK the data in0bc = 0x00; USB_EP0_HSNAK(); }
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 usb_irq(void) { switch(IVEC) { case INT_USBRESET: USBIRQ = 0x10; usb_state = DEFAULT; usb_current_config = 0; usb_current_alt_interface = 0; usb_bm_state = 0; break; case INT_SUDAV: USBIRQ = 0x01; isr_sudav(); break; case INT_SOF: USBIRQ = 0x02; break; case INT_SUTOK: USBIRQ = 0x04; packetizer_data_ptr = NULL; packetizer_data_size = 0; packetizer_pkt_size = 0; break; case INT_SUSPEND: USBIRQ = 0x08; break; case INT_EP0IN: IN_IRQ = 0x01; packetizer_isr_ep0_in(); break; case INT_EP0OUT: usb_handle_data(OUT0BUF, OUT0BC); OUT_IRQ = 0x01; OUT0BC=0xff; USB_EP0_HSNAK(); break; case INT_EP1IN: // Clear interrupt IN_IRQ = 0x02; IN1CS = 0x02; break; case INT_EP1OUT: // Clear interrupt OUT_IRQ = 0x02; OUT1BC = 0xff; break; default: break; } }
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 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(); } }
static void packetizer_isr_ep0_in() { uint8_t size, i; // We are getting a ep0in interupt when the host send ACK and do not have any more data to send if(packetizer_data_size == 0) { IN0BC = 0; USB_EP0_HSNAK(); return; } size = MIN(packetizer_data_size, packetizer_pkt_size); // Copy data to the USB-controller buffer memcpy(IN0BUF, packetizer_data_ptr, size); // Tell the USB-controller how many bytes to send // If a IN is received from host after this the USB-controller will send the data IN0BC = size; // Update the packetizer data packetizer_data_ptr += size; packetizer_data_size -= size; }
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(); } }