diff --git a/Makefile b/Makefile index 76c9543..8c5c173 100644 --- a/Makefile +++ b/Makefile @@ -26,7 +26,7 @@ CFLAGS += -nostdinc $(patsubst %,-I%,$(INCDIRS)) CFLAGS += -MD -MP -MF $(BUILD)/.dep/$(*F).d CFLAGS += -Wall -#CFLAGS += -Wextra +#CFLAGS += -Wextra #CFLAGS += -Wcast-align -Wimplicit -Wunused #CFLAGS += -Wpointer-arith -Wswitch #CFLAGS += -Wredundant-decls -Wreturn-type -Wshadow @@ -50,7 +50,7 @@ all: $(BUILD)/$(TARGET).elf $(BUILD)/$(TARGET).elf: $(patsubst %,$(BUILD)/%,$(AS_SRC:.s=.o) $(SRC:.c=.o)) @echo " Linking file: $@" @$(shell mkdir -p $(BUILD)/$(*D)) - @$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) + @$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) > /dev/null @$(OBJCOPY) -O binary $@ $@.bin @$(OBJCOPY) -O ihex $@ $@.hex @$(OBJDUMP) -h -S -C $@ > $@.lss diff --git a/include/usb_ch9.h b/include/usb_ch9.h index 533d7d0..d57bb99 100644 --- a/include/usb_ch9.h +++ b/include/usb_ch9.h @@ -8,7 +8,8 @@ * - linux/include/linux/usb/ch9.h * with minor modifications: * - type conversion (e.g. __u8 -> uint8_t) - * - usb_endpoint_descriptor: removed last 2 bytes + * - usb_endpoint_descriptor: removed last 2 bytes + * - usb_string_descriptor: wData has no size */ /*-------------------------------------------------------------------------*/ @@ -258,7 +259,7 @@ struct usb_string_descriptor { uint8_t bLength; uint8_t bDescriptorType; - uint16_t wData[1]; /* UTF-16LE encoded */ + uint16_t wData[]; /* UTF-16LE encoded */ } __attribute__ ((packed)); /* note that "string" zero is special, it holds language codes that diff --git a/src/at91_udp.c b/src/at91_udp.c index 5647bbc..6bdfb9b 100644 --- a/src/at91_udp.c +++ b/src/at91_udp.c @@ -39,11 +39,11 @@ struct udp_transfer { uint16_t address; uint16_t maxpkt; // TODO: last bank used / ping pong - + // TODO: direction (IN/OUT) uint16_t length; uint16_t curpos; - + char *data; void (*complete_cb)(void); // TODO: privdata? @@ -183,7 +183,7 @@ static void udp_configure_ep(const struct usb_endpoint_descriptor *desc) /* get endpoint type (ctrl, iso, bulb, int) */ uint32_t eptype = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; if (desc->bEndpointAddress & USB_ENDPOINT_DIR_MASK) - eptype |= 0x04; + eptype |= 0x04; /* get endpoint address, set Max Packet Size */ uint32_t address = desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; @@ -191,13 +191,13 @@ static void udp_configure_ep(const struct usb_endpoint_descriptor *desc) /* configure UDP endpoint and enable interrupt */ AT91C_UDP_CSR[address] = AT91C_UDP_EPEDS | (eptype << 8); - *AT91C_UDP_IER = (1 << address); + *AT91C_UDP_IER = (1 << address); } static void udp_fill_fifo(struct udp_transfer *trans) { uint16_t ep = trans->address; - + if (AT91C_UDP_CSR[ep] & AT91C_UDP_TXPKTRDY) { printf("TX!RDY\n\r"); return; @@ -212,7 +212,7 @@ static void udp_fill_fifo(struct udp_transfer *trans) AT91C_UDP_CSR[ep] |= AT91C_UDP_TXPKTRDY; } -static void udp_send_data(struct udp_transfer *trans, const char *data, +static void udp_send_data(struct udp_transfer *trans, const char *data, uint32_t length, void (*complete_cb)(void)) { if (trans->length != trans->curpos) { @@ -239,7 +239,7 @@ static void udp_send_stall(uint32_t ep) /* * set local address * (USB_REQ_SET_ADDRESS callback) - */ + */ static void udp_txcb_setaddress(void) { *AT91C_UDP_FADDR = (AT91C_UDP_FEN | current_address); @@ -249,7 +249,7 @@ static void udp_txcb_setaddress(void) /* * configure endpoints * (USB_REQ_SET_CONFIGURATION callback) - */ + */ static void udp_txcb_setconfig(void) { udp_configure_ep(&cfg_descriptor.notify_ep); @@ -262,14 +262,14 @@ static void udp_txcb_setconfig(void) static void udp_txcb_setinterface(void) { - printf("claim interface %d\n\r", current_interface); + printf("claim interface %d\n\r", current_interface); } static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req) { printf("typ:0x%02x req:0x%02x val:0x%04x idx:0x%04x len:0x%04x\n\r", req->bRequestType, req->bRequest, req->wValue, req->wIndex, req->wLength); - + switch (req->bRequestType & (USB_TYPE_MASK | USB_RECIP_MASK)) { case (USB_TYPE_STANDARD | USB_RECIP_DEVICE): /* 0x00/0x80 */ switch (req->bRequest) { @@ -277,7 +277,7 @@ static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req) current_address = req->wValue; udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setaddress); break; - + case USB_REQ_GET_DESCRIPTOR: /* 0x06 */ switch (req->wValue >> 8) { case USB_DT_DEVICE: /* 0x01 */ @@ -300,18 +300,18 @@ static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req) current_config = req->wValue; udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setconfig); break; - + default: udp_send_stall(0); break; } break; - + case (USB_TYPE_STANDARD | USB_RECIP_INTERFACE): /* 0x01/0x81 */ // TODO: follow current_interface switch (req->bRequest) { case USB_REQ_SET_INTERFACE: /* 0x0b */ - current_interface = req->wIndex; + current_interface = req->wValue; udp_send_data(&ep_transfer[0], NULL, 0, udp_txcb_setinterface); break; @@ -332,10 +332,9 @@ static void udp_handle_ctrlrequest(struct usb_ctrlrequest *req) udp_send_data(&ep_transfer[0], (const char *)&dfu_status, MIN(sizeof(struct dfu_status), req->wLength), NULL); break; - + case USB_CDC_REQ_SET_LINE_CODING: /* 0x20 */ // TODO: read 7 data bytes - udp_send_data(&ep_transfer[0], NULL, 0, NULL); break; case USB_CDC_REQ_SET_CONTROL_LINE_STATE: /* 0x22 */ @@ -368,21 +367,21 @@ static void udp_handle_ep(uint32_t ep) uint8_t *p; for (p = (uint8_t *)&req; p < (uint8_t *)(&req +1); p++) *p = AT91C_UDP_FDR[ep]; - + /* set data phase transfer direction */ if (req.bRequestType & USB_DIR_IN) *csr |= AT91C_UDP_DIR; - + /* clear interrupt (THIS MUST USE csr_clear_flags()!) */ csr_clear_flags(*csr, AT91C_UDP_RXSETUP); - - udp_handle_ctrlrequest(&req); + + udp_handle_ctrlrequest(&req); } - + /* transmit complete? */ if (*csr & AT91C_UDP_TXCOMP) { struct udp_transfer *trans = &ep_transfer[ep]; - + /* refill fifo, if transfer is incomplete */ if (trans->length != trans->curpos) udp_fill_fifo(trans); @@ -390,7 +389,7 @@ static void udp_handle_ep(uint32_t ep) /* execute callback when transfer is complete */ else if (trans->complete_cb) trans->complete_cb(); - + /* clear interrupt */ *csr &= ~(AT91C_UDP_TXCOMP); } @@ -398,7 +397,7 @@ static void udp_handle_ep(uint32_t ep) /* clear STALLSENT interrupt */ if (*csr & AT91C_UDP_STALLSENT) csr_clear_flags(*csr, (AT91C_UDP_STALLSENT | AT91C_UDP_FORCESTALL)); - + /* data ready to read? */ if (*csr & (AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1)) { uint16_t len = (*csr & AT91C_UDP_RXBYTECNT) >> 16; @@ -406,14 +405,14 @@ static void udp_handle_ep(uint32_t ep) printf("rx: "); while (len--) printf("0x%02x ", AT91C_UDP_FDR[ep]); - + printf("\n\r"); } else { /* clear a pending transfer! */ ep_transfer[ep].length = 0; ep_transfer[ep].curpos = 0; - } + } /* TODO: ping pong FIFOs */ if (*csr & AT91C_UDP_RX_DATA_BK0) @@ -430,9 +429,9 @@ static void udp_isr(void) if (isr & AT91C_UDP_ENDBUSRES) { printf("usb reset\n\r"); - + AT91S_UDP *udp = AT91C_BASE_UDP; - + /* reset all endpoints */ udp->UDP_RSTEP = (AT91C_UDP_EP0 | AT91C_UDP_EP1 | AT91C_UDP_EP2 | AT91C_UDP_EP3) ; @@ -447,7 +446,7 @@ static void udp_isr(void) ep_transfer[i].curpos = 0; } ep_transfer[0].maxpkt = 8; - + /* Configure endpoint0 as Control EP */ udp->UDP_CSR[0] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); @@ -457,7 +456,7 @@ static void udp_isr(void) AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_SOFINT | AT91C_UDP_WAKEUP; } - + /* Handle Endpoint Interrupts */ uint32_t i; for (i = 0; i < 4; i++) { @@ -466,7 +465,7 @@ static void udp_isr(void) } /* clear all unhandled interrupts */ - *AT91C_UDP_ICR = isr & (AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | + *AT91C_UDP_ICR = isr & (AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_ENDBUSRES | AT91C_UDP_WAKEUP); } @@ -479,7 +478,7 @@ void at91_udp_init(void) pio->PIO_OER = UDP_PULLUP; // TODO: needed? pio->PIO_PPUDR = UDP_VBUS_MON; - + /* UDPCK (48MHz) = PLLCK / 2 */ *AT91C_CKGR_PLLR |= AT91C_CKGR_USBDIV_1; @@ -494,7 +493,7 @@ void at91_udp_init(void) *AT91C_UDP_IDR = AT91C_UDP_EPINT0 | AT91C_UDP_EPINT1 | AT91C_UDP_EPINT2 | AT91C_UDP_EPINT3 | AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_SOFINT | AT91C_UDP_WAKEUP; - + *AT91C_UDP_ICR = AT91C_UDP_RXSUSP | AT91C_UDP_RXRSM | AT91C_UDP_SOFINT | AT91C_UDP_ENDBUSRES | AT91C_UDP_WAKEUP ; @@ -503,7 +502,7 @@ void at91_udp_init(void) aic->AIC_SMR[AT91C_ID_UDP] = IRQPRIO_UDP | AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL; aic->AIC_SVR[AT91C_ID_UDP] = (uint32_t)udp_isr; aic->AIC_IECR = (1 << AT91C_ID_UDP); - + pio_trigger_isr(UDP_VBUS_MON); }