From 6d50b8809673371afd5f0bf237c345fdff3e80e2 Mon Sep 17 00:00:00 2001 From: eddyem Date: Fri, 26 Apr 2019 14:01:40 +0300 Subject: [PATCH] some fixes in pl2303 --- F0-nolib/pl2303/Makefile | 5 +- F0-nolib/pl2303/main.c | 60 ++++++- F0-nolib/pl2303/pl2303.bin | Bin 6164 -> 6484 bytes F0-nolib/pl2303/usb.c | 2 +- F0-nolib/pl2303/usb_defs.h | 13 +- F0-nolib/pl2303/usb_lib.c | 315 +++++++++++++++++++++---------------- F0-nolib/pl2303/usb_lib.h | 30 ++-- 7 files changed, 257 insertions(+), 168 deletions(-) diff --git a/F0-nolib/pl2303/Makefile b/F0-nolib/pl2303/Makefile index b547ad8..38bef31 100644 --- a/F0-nolib/pl2303/Makefile +++ b/F0-nolib/pl2303/Makefile @@ -9,8 +9,7 @@ MCU = F042x6 DEFS += -DUSARTNUM=1 #DEFS += -DCHECK_TMOUT #DEFS += -DEBUG -# change this linking script depending on particular MCU model, -# for example, if you have STM32F103VBT6, you should write: +# change this linking script depending on particular MCU model LDSCRIPT = stm32f042k.ld INDEPENDENT_HEADERS= @@ -60,11 +59,13 @@ CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration CFLAGS += -Wredundant-decls $(INCLUDE) # -Wmissing-prototypes -Wstrict-prototypes CFLAGS += -fno-common -ffunction-sections -fdata-sections +#CGLAGS += -fno-stack-protector ############################################################################### # Linker flags LDFLAGS += --static -nostartfiles #--specs=nano.specs +#LDFLAGS += -fno-stack-protector LDFLAGS += -L$(LIB_DIR) LDFLAGS += -T$(LDSCRIPT) LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map diff --git a/F0-nolib/pl2303/main.c b/F0-nolib/pl2303/main.c index bf6edf1..d26b40f 100644 --- a/F0-nolib/pl2303/main.c +++ b/F0-nolib/pl2303/main.c @@ -22,6 +22,7 @@ #include "usart.h" #include "usb.h" #include "usb_lib.h" +#include // memcpy volatile uint32_t Tms = 0; @@ -53,18 +54,62 @@ void iwdg_setup(){ IWDG->KR = IWDG_REFRESH; /* (6) */ } -void linecoding_handler(usb_LineCoding *lc){ +static usb_LineCoding new_lc; +static uint8_t lcchange = 0; +static void show_new_lc(){ SEND("got new linecoding:"); - SEND(" baudrate="); printu(lc->dwDTERate); - SEND(", charFormat="); printu(lc->bCharFormat); - SEND(", parityType="); printu(lc->bParityType); - SEND(", dataBits="); printu(lc->bDataBits); + SEND(" baudrate="); printu(new_lc.dwDTERate); + SEND(", charFormat="); printu(new_lc.bCharFormat); + SEND(" ("); + switch(new_lc.bCharFormat){ + case USB_CDC_1_STOP_BITS: + usart_putchar('1'); + break; + case USB_CDC_1_5_STOP_BITS: + SEND("1.5"); + break; + case USB_CDC_2_STOP_BITS: + usart_putchar('2'); + break; + default: + usart_putchar('?'); + } + SEND(" stop bits), parityType="); printu(new_lc.bParityType); + SEND(" ("); + switch(new_lc.bParityType){ + case USB_CDC_NO_PARITY: + SEND("no"); + break; + case USB_CDC_ODD_PARITY: + SEND("odd"); + break; + case USB_CDC_EVEN_PARITY: + SEND("even"); + break; + case USB_CDC_MARK_PARITY: + SEND("mark"); + break; + case USB_CDC_SPACE_PARITY: + SEND("space"); + break; + default: + SEND("unknown"); + } + SEND(" parity), dataBits="); printu(new_lc.bDataBits); usart_putchar('\n'); + lcchange = 0; +} + +void linecoding_handler(usb_LineCoding *lc){ + memcpy(&new_lc, lc, sizeof(usb_LineCoding)); + lcchange = 1; } void clstate_handler(uint16_t val){ SEND("change control line state to "); printu(val); + if(val & CONTROL_DTR) SEND(" (DTR)"); + if(val & CONTROL_RTS) SEND(" (RTS)"); usart_putchar('\n'); } @@ -120,6 +165,7 @@ int main(void){ case 'L': USB_send("Very long test string for USB (it's length is more than 64 bytes\n" "This is another part of the string! Can you see all of this?\n"); + SEND("Long test sent\n"); break; case 'R': SEND("Soft reset\n"); @@ -127,6 +173,7 @@ int main(void){ break; case 'S': USB_send("Test string for USB\n"); + SEND("Short test sent\n"); break; case 'W': SEND("Wait for reboot\n"); @@ -150,6 +197,9 @@ int main(void){ usart_send(txt); L = 0; } + if(lcchange){ + show_new_lc(); + } } return 0; } diff --git a/F0-nolib/pl2303/pl2303.bin b/F0-nolib/pl2303/pl2303.bin index 2cfbcef777494888ff35d6045b37da86606ead9f..10e5cd05adda90291fb6be63f4b572194b8aa48f 100755 GIT binary patch delta 4166 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 Ois9S%GGmicp8o^EQ<=&D delta 3692 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 PmPQ3QgBJl`KhpP~e00+j diff --git a/F0-nolib/pl2303/usb.c b/F0-nolib/pl2303/usb.c index e5a5832..f7fe8eb 100644 --- a/F0-nolib/pl2303/usb.c +++ b/F0-nolib/pl2303/usb.c @@ -109,7 +109,7 @@ void USB_setup(){ void usb_proc(){ if(USB_GetState() == USB_CONFIGURE_STATE){ // USB configured - activate other endpoints if(!usbON){ // endpoints not activated - MSG("Configured; activate other endpoints\n"); + SEND("Configure endpoints\n"); // make new BULK endpoint // Buffer have 1024 bytes, but last 256 we use for CAN bus (30.2 of RM: USB main features) EP_Init(1, EP_TYPE_INTERRUPT, 10, 0, EP1_Handler); // IN1 - transmit diff --git a/F0-nolib/pl2303/usb_defs.h b/F0-nolib/pl2303/usb_defs.h index 78a59e9..6ac673c 100644 --- a/F0-nolib/pl2303/usb_defs.h +++ b/F0-nolib/pl2303/usb_defs.h @@ -27,18 +27,21 @@ #include -#define USB_BTABLE_BASE 0x40006000 +/** + * Buffers size definition + **/ // !!! when working with CAN bus change USB_BTABLE_SIZE to 768 !!! #define USB_BTABLE_SIZE 1024 // first 64 bytes of USB_BTABLE are registers! #define USB_EP0_BASEADDR 64 -// for USB FS EP0 buffers are from 8 to 64 bytes long -#define USB_EP0_BUFSZ 8 -// USB transmit buffer size +// for USB FS EP0 buffers are from 8 to 64 bytes long (64 for PL2303) +#define USB_EP0_BUFSZ 64 +// USB transmit buffer size (64 for PL2303) #define USB_TXBUFSZ 64 -// USB receive buffer size +// USB receive buffer size (64 for PL2303) #define USB_RXBUFSZ 64 +#define USB_BTABLE_BASE 0x40006000 #undef USB_BTABLE #define USB_BTABLE ((USB_BtableDef *)(USB_BTABLE_BASE)) #define USB_ISTR_EPID 0x0000000F diff --git a/F0-nolib/pl2303/usb_lib.c b/F0-nolib/pl2303/usb_lib.c index 0e5935d..ffeb9b6 100644 --- a/F0-nolib/pl2303/usb_lib.c +++ b/F0-nolib/pl2303/usb_lib.c @@ -26,6 +26,9 @@ #include // memcpy #include "usart.h" +ep_t endpoints[ENDPOINTS_NUM]; + +static usb_dev_t USB_Dev; static usb_LineCoding lineCoding = {115200, 0, 0, 8}; static config_pack_t setup_packet; static uint8_t ep0databuf[EP0DATABUF_SIZE]; @@ -33,15 +36,23 @@ static uint8_t ep0dbuflen = 0; usb_LineCoding getLineCoding(){return lineCoding;} -const uint8_t USB_DeviceDescriptor[] = { +// definition of parts common for USB_DeviceDescriptor & USB_DeviceQualifierDescriptor +#define bcdUSB_L 0x10 +#define bcdUSB_H 0x01 +#define bDeviceClass 0 +#define bDeviceSubClass 0 +#define bDeviceProtocol 0 +#define bNumConfigurations 1 + +static const uint8_t USB_DeviceDescriptor[] = { 18, // bLength - 0x01, // bDescriptorType - USB_DEVICE_DESC_TYPE - 0x10, // bcdUSB_L - 1.10 - 0x01, // bcdUSB_H - 0x00, // bDeviceClass - USB_COMM - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - 0x40, // bMaxPacketSize + 0x01, // bDescriptorType - Device descriptor + bcdUSB_L, // bcdUSB_L - 1.10 + bcdUSB_H, // bcdUSB_H + bDeviceClass, // bDeviceClass - USB_COMM + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0_BUFSZ, // bMaxPacketSize 0x7b, // idVendor_L PL2303: VID=0x067b, PID=0x2303 0x06, // idVendor_H 0x03, // idProduct_L @@ -51,23 +62,23 @@ const uint8_t USB_DeviceDescriptor[] = { 0x01, // iManufacturer 0x02, // iProduct 0x00, // iSerialNumber - 0x01 // bNumConfigurations + bNumConfigurations // bNumConfigurations }; -const uint8_t USB_DeviceQualifierDescriptor[] = { +static const uint8_t USB_DeviceQualifierDescriptor[] = { 10, //bLength - 0x06, // bDescriptorType - 0x10, // bcdUSB_L - 0x01, // bcdUSB_H - 0x00, // bDeviceClass - 0x00, // bDeviceSubClass - 0x00, // bDeviceProtocol - 0x40, // bMaxPacketSize0 - 0x01, // bNumConfigurations + 0x06, // bDescriptorType - Device qualifier + bcdUSB_L, // bcdUSB_L + bcdUSB_H, // bcdUSB_H + bDeviceClass, // bDeviceClass + bDeviceSubClass, // bDeviceSubClass + bDeviceProtocol, // bDeviceProtocol + USB_EP0_BUFSZ, // bMaxPacketSize0 + bNumConfigurations, // bNumConfigurations 0x00 // Reserved }; -const uint8_t USB_ConfigDescriptor[] = { +static const uint8_t USB_ConfigDescriptor[] = { /*Configuration Descriptor*/ 0x09, /* bLength: Configuration Descriptor size */ 0x02, /* bDescriptorType: Configuration */ @@ -122,12 +133,9 @@ const uint8_t USB_ConfigDescriptor[] = { _USB_LANG_ID_(USB_StringLangDescriptor, LANG_US); // these descriptors are not used in PL2303 emulator! -_USB_STRING_(USB_StringSerialDescriptor, u"0") -_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc.") -_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller") - -static usb_dev_t USB_Dev; -ep_t endpoints[ENDPOINTS_NUM]; +_USB_STRING_(USB_StringSerialDescriptor, u"0"); +_USB_STRING_(USB_StringManufacturingDescriptor, u"Prolific Technology Inc."); +_USB_STRING_(USB_StringProdDescriptor, u"USB-Serial Controller"); /* * default handlers @@ -149,12 +157,8 @@ void WEAK break_handler(){ // handler of vendor requests void WEAK vendor_handler(config_pack_t *packet){ - /*SEND("Vendor, reqt="); - printuhex(packet->bmRequestType); - SEND(", wval="); - printuhex(packet->wValue); - usart_putchar('\n');*/ if(packet->bmRequestType & 0x80){ // read + //SEND("Read"); uint8_t c; switch(packet->wValue){ case 0x8484: @@ -171,8 +175,92 @@ void WEAK vendor_handler(config_pack_t *packet){ } EP_WriteIRQ(0, &c, 1); }else{ // write ZLP + //SEND("Write"); EP_WriteIRQ(0, (uint8_t *)0, 0); } + /*SEND(" vendor, reqt="); + printuhex(packet->bmRequestType); + SEND(", wval="); + printuhex(packet->wValue); + usart_putchar('\n');*/ +} + + +#ifdef EBUG + uint8_t _2wr = 0; + #define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0) +#else + #define WRITEDUMP(str) +#endif +static void wr0(const uint8_t *buf, uint16_t size){ + if(setup_packet.wLength < size) size = setup_packet.wLength; + EP_WriteIRQ(0, buf, size); +} + +static inline void get_descriptor(){ + switch(setup_packet.wValue){ + case DEVICE_DESCRIPTOR: + wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); + break; + case CONFIGURATION_DESCRIPTOR: + wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); + break; + case STRING_LANG_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); + break; + case STRING_MAN_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); + break; + case STRING_PROD_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); + break; + case STRING_SN_DESCRIPTOR: + wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); + break; + case DEVICE_QUALIFIER_DESCRIPTOR: + wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); + break; + default: + WRITEDUMP("UNK_DES"); + break; + } +} + +static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) +static inline void std_d2h_req(){ + uint16_t status = 0; // bus powered + switch(setup_packet.bRequest){ + case GET_DESCRIPTOR: + get_descriptor(); + break; + case GET_STATUS: + EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered + break; + case GET_CONFIGURATION: + WRITEDUMP("GET_CONFIGURATION"); + EP_WriteIRQ(0, &configuration, 1); + break; + default: + WRITEDUMP("80:WR_REQ"); + break; + } +} + +static inline void std_h2d_req(){ + switch(setup_packet.bRequest){ + case SET_ADDRESS: + // new address will be assigned later - after acknowlegement or request to host + USB_Dev.USB_Addr = setup_packet.wValue; + break; + case SET_CONFIGURATION: + // Now device configured + USB_Dev.USB_Status = USB_CONFIGURE_STATE; + configuration = setup_packet.wValue; + break; + default: + WRITEDUMP("0:WR_REQ"); + break; + } } /* @@ -186,123 +274,70 @@ bmRequestType: 76543210 * @param ep - endpoint state * @return data written to EP0R */ -uint16_t EP0_Handler(ep_t ep){ - uint16_t status = 0; // bus powered +static uint16_t EP0_Handler(ep_t ep){ uint16_t epstatus = ep.status; // EP0R on input -> return this value after modifications - static uint8_t configuration = 0; // reply for GET_CONFIGURATION (==1 if configured) - void wr0(const uint8_t *buf, uint16_t size){ - if(setup_packet.wLength < size) size = setup_packet.wLength; - EP_WriteIRQ(0, buf, size); - } -#ifdef EBUG - uint8_t _2wr = 0; - #define WRITEDUMP(str) do{MSG(str); _2wr = 1;}while(0) -#else - #define WRITEDUMP(str) -#endif + uint8_t reqtype = setup_packet.bmRequestType & 0x7f; + uint8_t dev2host = (setup_packet.bmRequestType & 0x80) ? 1 : 0; if ((ep.rx_flag) && (ep.setup_flag)){ - if (setup_packet.bmRequestType == 0x80){ // standard device request (device to host) - switch(setup_packet.bRequest){ - case GET_DESCRIPTOR: - switch(setup_packet.wValue){ - case DEVICE_DESCRIPTOR: - wr0(USB_DeviceDescriptor, sizeof(USB_DeviceDescriptor)); - break; - case CONFIGURATION_DESCRIPTOR: - wr0(USB_ConfigDescriptor, sizeof(USB_ConfigDescriptor)); - break; - case STRING_LANG_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringLangDescriptor, STRING_LANG_DESCRIPTOR_SIZE_BYTE); - break; - case STRING_MAN_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringManufacturingDescriptor, USB_StringManufacturingDescriptor.bLength); - break; - case STRING_PROD_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringProdDescriptor, USB_StringProdDescriptor.bLength); - break; - case STRING_SN_DESCRIPTOR: - wr0((const uint8_t *)&USB_StringSerialDescriptor, USB_StringSerialDescriptor.bLength); - break; - case DEVICE_QALIFIER_DESCRIPTOR: - wr0(USB_DeviceQualifierDescriptor, USB_DeviceQualifierDescriptor[0]); - break; - default: - WRITEDUMP("UNK_DES"); - break; - } - break; - case GET_STATUS: - EP_WriteIRQ(0, (uint8_t *)&status, 2); // send status: Bus Powered - break; - case GET_CONFIGURATION: - WRITEDUMP("GET_CONFIGURATION"); - EP_WriteIRQ(0, &configuration, 1); - break; - default: - WRITEDUMP("80:WR_REQ"); - break; - } - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); - }else if(setup_packet.bmRequestType == 0x00){ // standard device request (host to device) - switch(setup_packet.bRequest){ - case SET_ADDRESS: - // new address will be assigned later - after acknowlegement or request to host - USB_Dev.USB_Addr = setup_packet.wValue; - break; - case SET_CONFIGURATION: - // Now device configured - USB_Dev.USB_Status = USB_CONFIGURE_STATE; - configuration = setup_packet.wValue; - break; - default: - WRITEDUMP("0:WR_REQ"); - break; - } - // send ZLP - EP_WriteIRQ(0, (uint8_t *)0, 0); - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); - }else if(setup_packet.bmRequestType == 0x02){ // standard endpoint request (host to device) - if (setup_packet.bRequest == CLEAR_FEATURE){ - // send ZLP + switch(reqtype){ + case STANDARD_DEVICE_REQUEST_TYPE: // standard device request + if(dev2host){ + std_d2h_req(); + }else{ + std_h2d_req(); + // send ZLP + EP_WriteIRQ(0, (uint8_t *)0, 0); + } + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + case STANDARD_ENDPOINT_REQUEST_TYPE: // standard endpoint request + if (setup_packet.bRequest == CLEAR_FEATURE){ + // send ZLP + EP_WriteIRQ(0, (uint8_t *)0, 0); + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + }else{ + WRITEDUMP("02:WR_REQ"); + } + break; + case VENDOR_REQUEST_TYPE: + vendor_handler(&setup_packet); + epstatus = SET_NAK_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + case CONTROL_REQUEST_TYPE: + switch(setup_packet.bRequest){ + case GET_LINE_CODING: + EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); + break; + case SET_LINE_CODING: // omit this for next stage, when data will come + break; + case SET_CONTROL_LINE_STATE: + clstate_handler(setup_packet.wValue); + break; + case SEND_BREAK: + break_handler(); + break; + default: + WRITEDUMP("undef control req"); + } + if(!dev2host) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement + epstatus = SET_VALID_RX(epstatus); + epstatus = SET_VALID_TX(epstatus); + break; + default: EP_WriteIRQ(0, (uint8_t *)0, 0); epstatus = SET_NAK_RX(epstatus); epstatus = SET_VALID_TX(epstatus); - }else{ - WRITEDUMP("02:WR_REQ"); - } - }else if((setup_packet.bmRequestType & VENDOR_MASK_REQUEST) == VENDOR_MASK_REQUEST){ // vendor request - vendor_handler(&setup_packet); - epstatus = SET_NAK_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); - }else if((setup_packet.bmRequestType & 0x7f) == CONTROL_REQUEST_TYPE){ // control request - switch(setup_packet.bRequest){ - case GET_LINE_CODING: - EP_WriteIRQ(0, (uint8_t*)&lineCoding, sizeof(lineCoding)); - break; - case SET_LINE_CODING: - break; - case SET_CONTROL_LINE_STATE: - clstate_handler(setup_packet.wValue); - break; - case SEND_BREAK: - break_handler(); - break; - default: - WRITEDUMP("undef control req"); - } - if((setup_packet.bmRequestType & 0x80) == 0) EP_WriteIRQ(0, (uint8_t *)0, 0); // write acknowledgement - epstatus = SET_VALID_RX(epstatus); - epstatus = SET_VALID_TX(epstatus); } }else if (ep.rx_flag){ // got data over EP0 or host acknowlegement if(ep.rx_cnt){ + EP_WriteIRQ(0, (uint8_t *)0, 0); if(setup_packet.bRequest == SET_LINE_CODING){ //WRITEDUMP("SET_LINE_CODING"); linecoding_handler((usb_LineCoding*)ep0databuf); } - EP_WriteIRQ(0, (uint8_t *)0, 0); } // Close transaction epstatus = CLEAR_DTOG_RX(epstatus); @@ -348,6 +383,7 @@ uint16_t EP0_Handler(ep_t ep){ #endif return epstatus; } +#undef WRITEDUMP static uint16_t lastaddr = USB_EP0_BASEADDR; /** @@ -361,6 +397,7 @@ static uint16_t lastaddr = USB_EP0_BASEADDR; * @return 0 if all OK */ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t (*func)(ep_t ep)){ + if(number >= ENDPOINTS_NUM) return 4; // out of configured amount if(txsz > USB_BTABLE_SIZE || rxsz > USB_BTABLE_SIZE) return 1; // buffer too large if(lastaddr + txsz + rxsz >= USB_BTABLE_SIZE) return 2; // out of btable USB->EPnR[number] = (type << 9) | (number & USB_EPnR_EA); @@ -380,7 +417,7 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t USB_BTABLE->EP[number].USB_ADDR_RX = lastaddr; endpoints[number].rx_buf = (uint8_t *)(USB_BTABLE_BASE + lastaddr); lastaddr += rxsz; - // buffer size: Table127 of RM: BL_SIZE=1, NUM_BLOCK=1 + // buffer size: Table127 of RM USB_BTABLE->EP[number].USB_COUNT_RX = countrx << 10; endpoints[number].func = func; return 0; @@ -388,7 +425,6 @@ int EP_Init(uint8_t number, uint8_t type, uint16_t txsz, uint16_t rxsz, uint16_t // standard IRQ handler void usb_isr(){ - uint8_t n; if (USB->ISTR & USB_ISTR_RESET){ // Reinit registers USB->CNTR = USB_CNTR_RESETM | USB_CNTR_CTRM; @@ -404,7 +440,7 @@ void usb_isr(){ } if(USB->ISTR & USB_ISTR_CTR){ // EP number - n = USB->ISTR & USB_ISTR_EPID; + uint8_t n = USB->ISTR & USB_ISTR_EPID; // copy status register uint16_t epstatus = USB->EPnR[n]; // Calculate flags @@ -412,7 +448,7 @@ void usb_isr(){ endpoints[n].setup_flag = (epstatus & USB_EPnR_SETUP) ? 1 : 0; endpoints[n].tx_flag = (epstatus & USB_EPnR_CTR_TX) ? 1 : 0; // copy received bytes amount - endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX; + endpoints[n].rx_cnt = USB_BTABLE->EP[n].USB_COUNT_RX & 0x3FF; // low 10 bits is counter // check direction if(USB->ISTR & USB_ISTR_DIR){ // OUT interrupt - receive data, CTR_RX==1 (if CTR_TX == 1 - two pending transactions: receive following by transmit) if(n == 0){ // control endpoint @@ -451,6 +487,7 @@ void usb_isr(){ */ void EP_WriteIRQ(uint8_t number, const uint8_t *buf, uint16_t size){ uint8_t i; + if(size > USB_TXBUFSZ) size = USB_TXBUFSZ; uint16_t N2 = (size + 1) >> 1; // the buffer is 16-bit, so we should copy data as it would be uint16_t uint16_t *buf16 = (uint16_t *)buf; diff --git a/F0-nolib/pl2303/usb_lib.h b/F0-nolib/pl2303/usb_lib.h index bb8828a..642e91e 100644 --- a/F0-nolib/pl2303/usb_lib.h +++ b/F0-nolib/pl2303/usb_lib.h @@ -32,6 +32,11 @@ // Max EP amount (EP0 + other used) #define ENDPOINTS_NUM 4 +// bmRequestType & 0x7f +#define STANDARD_DEVICE_REQUEST_TYPE 0 +#define STANDARD_ENDPOINT_REQUEST_TYPE 2 +#define VENDOR_REQUEST_TYPE 0x40 +#define CONTROL_REQUEST_TYPE 0x21 // bRequest, standard; for bmRequestType == 0x80 #define GET_STATUS 0x00 #define GET_DESCRIPTOR 0x06 @@ -46,21 +51,14 @@ #define GET_INTERFACE 0x0A // unused #define SET_INTERFACE 0x0B // unused #define SYNC_FRAME 0x0C // unused - -// vendor requests -#define VENDOR_MASK_REQUEST 0x40 -#define VENDOR_READ_REQUEST_TYPE 0xc0 -#define VENDOR_WRITE_REQUEST_TYPE 0x40 -#define VENDOR_REQUEST 0x01 - -#define CONTROL_REQUEST_TYPE 0x21 +#define VENDOR_REQUEST 0x01 // unused // Class-Specific Control Requests -#define SEND_ENCAPSULATED_COMMAND 0x00 -#define GET_ENCAPSULATED_RESPONSE 0x01 -#define SET_COMM_FEATURE 0x02 -#define GET_COMM_FEATURE 0x03 -#define CLEAR_COMM_FEATURE 0x04 +#define SEND_ENCAPSULATED_COMMAND 0x00 // unused +#define GET_ENCAPSULATED_RESPONSE 0x01 // unused +#define SET_COMM_FEATURE 0x02 // unused +#define GET_COMM_FEATURE 0x03 // unused +#define CLEAR_COMM_FEATURE 0x04 // unused #define SET_LINE_CODING 0x20 #define GET_LINE_CODING 0x21 #define SET_CONTROL_LINE_STATE 0x22 @@ -77,7 +75,7 @@ #define STRING_MAN_DESCRIPTOR 0x301 #define STRING_PROD_DESCRIPTOR 0x302 #define STRING_SN_DESCRIPTOR 0x303 -#define DEVICE_QALIFIER_DESCRIPTOR 0x600 +#define DEVICE_QUALIFIER_DESCRIPTOR 0x600 // EPnR bits manipulation #define CLEAR_DTOG_RX(R) (R & USB_EPnR_DTOG_RX) ? R : (R & (~USB_EPnR_DTOG_RX)) @@ -121,7 +119,7 @@ static const struct name \ uint16_t bString[(sizeof(str) - 2) / 2]; \ \ } \ -name = {sizeof(name), 0x03, str}; +name = {sizeof(name), 0x03, str} #define _USB_LANG_ID_(name, lng_id) \ \ @@ -132,7 +130,7 @@ static const struct name \ uint16_t bString; \ \ } \ -name = {0x04, 0x03, lng_id}; +name = {0x04, 0x03, lng_id} #define STRING_LANG_DESCRIPTOR_SIZE_BYTE (4) // EP0 configuration packet