Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * usb.c
- *
- * Created: 29.12.2012 17:25:47
- * Author: Ondra
- */
- #include "usb.h"
- #include "cdc/cdc.h"
- //#ifdef DEBUG
- #include "../../uart/uart.h"
- //#endif
- volatile USB_RAM_t usb_ram;
- byte USB_State;
- uint8_t USB_New_Addr;
- void USB_Init()
- {
- uart_println("USB drv: initializing");
- Clock_Set_USB(32); // 32MHz
- PMIC_Enable(PMIC_HILVLEN_bm | PMIC_MEDLVLEN_bm | PMIC_LOLVLEN_bm);
- USB_Set_Registers();
- USB_Reset();
- uart_println("USB drv: init done");
- }
- void USB_Reset()
- {
- USB_Reset_Everything();
- USB_Set_Address(0);
- USB_State = Powered;
- }
- void USB_Reset_Everything()
- {
- USB_Endpoint_Reset(0);
- USB_Endpoint_Reset(1);
- USB_Endpoint_Reset(2);
- USB_Endpoint_Reset(3);
- USB_Endpoint_Reset(4);
- USB_Endpoint_Reset(5);
- USB_Endpoint_Set_CTRL(0, USB_EP_TYPE_CONTROL_gc | USB_EP_BUFSIZE_64_gc);
- USB_Endpoint_Set_CTRL(1, USB_EP_TYPE_CONTROL_gc | USB_EP_BUFSIZE_64_gc); // no AZLP nor auxdata -- we are doing it manually due to sillicon errata on A1U chips
- USB_Endpoint_Set_CTRL(2, USB_EP_TYPE_DISABLE_gc);
- USB_Endpoint_Set_CTRL(3, USB_EP_TYPE_BULK_gc | USB_EP_BUFSIZE_64_gc);
- USB_Endpoint_Set_CTRL(4, USB_EP_TYPE_BULK_gc | USB_EP_BUFSIZE_64_gc);
- USB_Endpoint_Set_CTRL(5, USB_EP_TYPE_BULK_gc | USB_EP_BUFSIZE_64_gc); // actually interrupt, but they are the same for XMega
- USB_Set_DATA(EP_CTRL_OUT, usb_ram.payload[0]);
- USB_Set_DATA(EP_DATA_OUT, usb_ram.payload[1]);
- USB_Set_DATA(EP_NOTIF_OUT, usb_ram.payload[2]);
- }
- void USB_Set_Registers()
- {
- USB.EPPTR = (u16)usb_ram.endpoint;
- USB.INTCTRLA = USB_INTLVL_HI_gc | /*USB_SOFIE_bm | */USB_BUSEVIE_bm/* | USB_BUSERRIE_bm | USB_STALLIE_bm*/;
- USB.INTCTRLB = USB_TRNIE_bm | USB_SETUPIE_bm;
- USB.CTRLA = USB_ENABLE_bm | USB_SPEED_bm | (XBOOT_ENDPOINTS - 1) | USB_FIFOEN_bm;
- }
- void USB_Attach()
- {
- USB.CTRLB |= USB_ATTACH_bm;
- }
- void USB_Detach()
- {
- USB.CTRLB &= ~USB_ATTACH_bm;
- }
- void USB_Fetch_Descriptor(USB_DeviceRequest_t* Packet)
- {
- switch(Packet->wValue >> 8)
- {
- case USB_Request_Descriptor_DEVICE:
- USB_Send_Data(EP_CTRL_IN, &USB_Descriptor_Device, USB_Descriptor_Device.bLength);
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- uart_println("Descriptor device");
- break;
- case USB_Request_Descriptor_CONFIGURATION:
- USB_Send_Data(EP_CTRL_IN, &USB_Descriptor_Configuration, USB_Descriptor_Configuration.Configuration.wTotalLength)
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- uart_println("Descriptor configuration");
- break;
- case USB_Request_Descriptor_STRING:
- switch(Packet->wValue & 0xFF)
- {
- case USB_STRING_MANUFACTURER:
- USB_Send_Data(EP_CTRL_IN, &USB_Descriptor_String_Manufacturer, USB_Descriptor_String_Manufacturer.bLength);
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- uart_println("Descriptor string manufacturer");
- break;
- case USB_STRING_PRODUCT:
- USB_Send_Data(EP_CTRL_IN, &USB_Descriptor_String_Product, USB_Descriptor_String_Product.bLength);
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- uart_println("Descriptor string product");
- break;
- case USB_STRING_LIST:
- USB_Send_Data(EP_CTRL_IN, &USB_Descriptor_Language, USB_Descriptor_Language.bLength);
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- uart_println("Descriptor string list");
- break;
- }
- break;
- }
- }
- void USB_Process_Setup_Packet()
- {
- USB_DeviceRequest_t* Request = (USB_DeviceRequest_t*) ((u8*)usb_ram.endpoint[0].DATAPTR);
- USB_Set_AUXDATA(EP_DATA_IN, 0); // clear any pending data
- if((Request->bmRequestType & USB_Request_Type_MASK) == USB_Request_Type_CLASS)
- {
- uart_println("CDC Packet");
- USB_CDC_Setup_Packet(Request);
- return;
- }
- else if((Request->bmRequestType & USB_Request_Type_MASK) == USB_Request_Type_VENDOR)
- {
- uart_println("?? vendor packet");
- // error condition
- }
- else if((Request->bmRequestType & USB_Request_Type_STANDARD) == USB_Request_Type_STANDARD)
- { // regular setup packet
- switch(Request->bRequest)
- {
- case USB_Request_GET_DESCRIPTOR:
- USB_Fetch_Descriptor(Request);
- break;
- case USB_Request_SET_ADDRESS:
- uart_println("Set address packet");
- USB_State = AddressPending;
- USB_New_Addr = Request->wValue & 0x7F;
- USB_ZLP(EP_CTRL_IN);
- USB_Ack(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- break;
- case USB_Request_SET_CONFIGURATION:
- uart_println("Set configuration packet");
- USB_ZLP(EP_CTRL_IN);
- USB_Ack(EP_CTRL_OUT);
- USB_Ack(EP_CTRL_IN);
- break;
- }
- }
- //uart_println("This was setup packet. Data: ");
- memdump(Request, sizeof(USB_DeviceRequest_t));
- uart_println("\r\n");
- }
- ISR(USB_TRNCOMPL_vect)
- {
- USB_Ack_TRNCOMPL();
- if(USB_Is_Setup_Packet())
- {
- USB_Ack_Setup_Packet();
- USB_Process_Setup_Packet();
- return;
- }
- u8 EP = (u8)USB_Get_EP_From_FIFO();
- u16 cnt;
- u16 aux;
- switch(EP)
- {
- case EP_CTRL_OUT: // PC => device
- // let's hope for now that PC won't send >64 bytes of data on control endpoints
- uart_println("TRNCOMPL on ctrl out FIFO");
- memdump(usb_ram.payload[EP_CTRL_OUT], XBOOT_DATASIZE);
- break;
- case EP_CTRL_IN: // device => PC
- uart_println("TRNCOMPL on ctrl in FIFO");
- // manage auxiliary data + ZLP
- cnt = USB_Get_CNT(EP_CTRL_IN);
- aux = USB_Get_AUXDATA(EP_CTRL_IN);
- if(cnt == aux && aux != 0) // aux != 0 for packets with 0 length in the beginning.
- {
- USB_ZLP(EP_CTRL_IN);
- USB_Ack(EP_CTRL_IN);
- uart_println("Sending ZLP");
- }
- else if (cnt < aux)
- {
- aux -= cnt; //"cnt" sent
- USB_Set_AUXDATA(EP_CTRL_IN, aux); // set new auxiliary data
- USB_Set_DATA(EP_CTRL_IN, USB_Get_DATA(EP_CTRL_IN) + cnt); // move ptr by cnt further. Might not have been full XBOOT_DATASIZE (for example only the first 8B of device descriptor for backward compatibility)
- USB_Set_CNT(EP_CTRL_IN, MIN(aux, cnt)); // now send either aux or cnt - what is smaller. If aux is smaller than max data, then send aux, otherwise max data (cnt)
- USB_Ack(EP_CTRL_IN);
- uart_println("Sending another CNT AUX:");
- //usart_u16(cnt);
- memdump(&cnt, 2);
- //usart_u16(aux);
- memdump(&aux, 2);
- uart_println("");
- }
- else
- {
- // error, shouldn't happen?!
- uart_println("error! cnt > aux!");
- }
- if(USB_State == AddressPending)
- {
- USB_Set_Address(USB_New_Addr);
- USB_State = Addressed;
- uart_println("Setting new address");
- }
- break;
- /*case EP_DATA_IN: // uart rx
- break;
- case EP_DATA_OUT: // uart tx
- break;
- case EP_NOTIF_IN:
- break;*/
- default: // CDC packet or error condition
- USB_CDC_Data_Packet(EP);
- return;
- break;
- }
- }
- ISR(USB_BUSEVENT_vect)
- {
- if(USB.INTFLAGSASET & USB_SOFIF_bm)
- {
- USB.INTFLAGSACLR = USB_SOFIF_bm;
- return;
- }
- if(USB.INTFLAGSASET & USB_RSTIF_bm)
- {
- USB.INTFLAGSACLR = USB_RSTIF_bm;
- uart_println("Resetting.");
- USB_Detach();
- USB_Reset();
- USB_Attach();
- return;
- }
- USB.INTFLAGSACLR = 0xFF; // clear all the USB A flags
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement