From cd17777c4dcae7025a4f52c66436fc4ac2d93851 Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Fri, 29 Nov 2024 22:55:08 +0300 Subject: [PATCH] still don't work properly --- F1:F103/I2C_tiny/I2Ctiny.bin | Bin 4916 -> 5344 bytes F1:F103/I2C_tiny/i2c.c | 245 +++++++++-------------------------- F1:F103/I2C_tiny/i2c.h | 11 +- F1:F103/I2C_tiny/usbdev.c | 87 +++---------- 4 files changed, 83 insertions(+), 260 deletions(-) diff --git a/F1:F103/I2C_tiny/I2Ctiny.bin b/F1:F103/I2C_tiny/I2Ctiny.bin index c91e96c66c86620cfc11e382629445e15b5d8835..aea49a359e91378825f7126bfe2bd3c3db2e8c28 100755 GIT binary patch delta 2102 zcmb_dUrbwN6hGf>X>b1krMHEyz*2jsf-M;gGZTkNLru5!;^rS_mVsEJ4<#{M7lP0s zyA5K3`a-;KG||MFCGNp#2M?oeO^n9ZHfo&o<-V9Dyx2t|g97!O+tPIqIOHZktGIW4vSpdF-vbj%S-;ZoaNKJ32;ozD5KK^Ab9|+oM|Ibbj`21%O zFaO`clrwBle*bH@sS6b^7vn>)nlec4Se?{56)Z5_YD$kQ$XK7d6H0s=JJ}B4X+udY z!Odo=HOhLOVIks_!0S#3_*|S7q~w@A94zoUWz;6+#~Q=Ibr60UZ9waK)V~oFA|{FV zE+&kU$?KjoNFB-pCdeN23WE>;8y5g83oI=v1E+{_BR<9btXo zH)K1d){m1ZU4heq??LX#nw2H%m0IVMDNp#)S}=HN?X_SsB_x>WSKBnb8!;uuN#~Rp z`gRQHWYzJQbGwxMh@3NWo^7aEaXAh_8B`PM0RQPF4qX)Et`LtTEg(sdIZPDI;jaGlb-Ucaf%a0g+Jw};blA(oCaAD_cY%1DdVpeIx_?u0mtAXg!^j0Lfe8i;f@KjulNKheDoOXpA#K9fNP?J!zQ1-QK96{Z} z(p;tCDF0?@EB;AJcF#H`17gEk>?_3{`FgDs=1RV_D(9$SDD$`Z1MUA3B;j+Tq?2<}U@s}89FshRfXlYHP= zrIGuF>ws(Dam;mW$0eODK)-vmZzJ9YFK5$ZD^cM^8j5wzgjdU&)+y3` zRXyg&rN>xrdNe(=GPc;S<_Q4Jff)fD-6iJ+Y(zZ@hoUtl0R+ML${x)K#4Mzypt zygeOt;Pn;JX>$x2kH&)^l#x33A#a}2*Pqb&?Dr`7a=Hz((nOoih6R@3GHceJBO^CmA+@Ww_~`9bUy-C`x${>u)R9EJuX_)QYGT!}clhH0guN z@0J7w9c1A7x#A5yy=(oHL$J;D*YS1hZoR_laTA8|3XDJiRU?fT+2M0|$c1{=fFEW} z4<1Lw(I8XSY<_>o=I(vOibmgKN_3NuoJS-2?CjpBCuGVWBxR&&rH#&?M^h{${~pRP K$`>dB^zk?Ux}*O9 delta 1594 zcmcJPT}V@57{{OYY;(uCxwFl5Oq0`AQmhZn(jyhs^4jl{xum9_$t8)Gx;_$yNMh}sC z2lN*R(=GWP+dP=w_}2;Ed8o03O#)c&Tr&uFTR2Z`oK;XiClrc$ygy!R^5tNJ##5V) zphm`;103UkdT@Z2(4guOQ$+4>&m!iJDYM{>V?KX@OImPC5LbVd7T%|*Q+*75Xpj18 z=*A*M*vbiKcmg8(l)#2ZItQRX;T!c`@g>FSuBUBETe2-FHgqZCL;-fw>!1jB4X%Z_ zXQg+Gv%vjCggBo9^d0L6iWZ+S_A9?pQR{-ZHtmP!R!hj2>;StW$_m7438>^CtHq}j z7<__=IRl16#PbCB@W|~YIIso%NwKiKVG!)=rxCDSxmRJ=PyIm6i3Y`>Up<$nusBD> zgeWa^OH2$RAj=9HfQNW#Q}S?34p!T%r%2C{ge^X!0`@biHVa1>Wm+csJljfo=}h)E z;-V&vEyN{{W+)9H-CT=u(-P&npC}E{r`Sj?-Bum0%Zb&J5@}abPkvp3-jt#KhLk!r zunj0L%Dzl#YF?&h##1y;Q_ApU$f=noD(vb;LQAw2`F+{IK1Mx5Ng2&$(@WYD26PJG zM|=yV#QW<8`cCVWLp=hu}0r?bpQYW diff --git a/F1:F103/I2C_tiny/i2c.c b/F1:F103/I2C_tiny/i2c.c index 4831473..d1297c8 100644 --- a/F1:F103/I2C_tiny/i2c.c +++ b/F1:F103/I2C_tiny/i2c.c @@ -29,28 +29,34 @@ extern volatile uint32_t Tms; // current addresses for read/write (should be set with i2c_set_addr7) static uint8_t addr7r = 0, addr7w = 0; +void i2c_set_addr7(uint8_t addr){ + addr7w = addr << 1; + addr7r = addr7w | 1; +} + +static uint8_t aflag = 0; +static uint32_t sctr = 0; + /* * PB10/PB6 - I2C_SCL, PB11/PB7 - I2C_SDA or remap @ PB8 & PB9 */ void i2c_setup(){ - RCC->APB1ENR &= ~RCC_APB1ENR_I2C1EN; - I2C1->CR1 = I2C_CR1_SWRST; + ++sctr; + //RCC->APB1RSTR = RCC_APB1RSTR_I2C1RST; // reset I2C + //RCC->APB1RSTR = 0; + I2C1->CR1 = 0; I2C1->SR1 = 0; RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; - GPIOB->CRL = (GPIOB->CRL & ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7)) | - CRL(6, CNF_AFOD | MODE_NORMAL) | CRL(7, CNF_AFOD | MODE_NORMAL); RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; + GPIOB->CRL = (GPIOB->CRL & ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7)) | + CRL(6, CNF_AFOD | MODE_NORMAL) | CRL(7, CNF_AFOD | MODE_NORMAL); I2C1->CR2 = 8; // FREQR=8MHz, T=125ns I2C1->TRISE = 9; // (9-1)*125 = 1mks I2C1->CCR = 40; // normal mode, 8MHz/2/40 = 100kHz I2C1->CR1 = I2C_CR1_PE; // enable periph } -void i2c_set_addr7(uint8_t addr){ - addr7w = addr << 1; - addr7r = addr7w | 1; -} - +#if 0 // wait for event evt no more than 2 ms #define I2C_WAIT(evt) do{ register uint32_t wait4 = Tms + 2; \ while(Tms < wait4 && !(evt)) IWDG->KR = IWDG_REFRESH; \ @@ -60,203 +66,50 @@ void i2c_set_addr7(uint8_t addr){ while(Tms < wait4 && (I2C1->SR2 & I2C_SR2_BUSY)) IWDG->KR = IWDG_REFRESH; \ if(I2C1->SR2 & I2C_SR2_BUSY){I2C1->CR1 |= I2C_CR1_SWRST; return I2C_LINEBUSY;}\ }while(0) +#endif -// start writing -static i2c_status i2c_7bit_startw(){ - i2c_status ret = I2C_LINEBUSY; - if(I2C1->CR1 != I2C_CR1_PE) i2c_setup(); - if(I2C1->SR1) I2C1->SR1 = 0; // clear NACK and other problems - (void) I2C1->SR2; - I2C_LINEWAIT(); - DBG("linew\n"); - I2C1->CR1 |= I2C_CR1_START; // generate start sequence - I2C_WAIT(I2C1->SR1 & I2C_SR1_SB); // wait for SB - DBG("SB\n"); - (void) I2C1->SR1; // clear SB - I2C1->DR = addr7w; // set address - I2C_WAIT(I2C1->SR1 & I2C_SR1_ADDR); // wait for ADDR flag (timeout @ NACK) - DBG("ADDR\n"); - if(I2C1->SR1 & I2C_SR1_AF){ // NACK - return I2C_NACK; - } - DBG("ACK\n"); - (void) I2C1->SR2; // clear ADDR - ret = I2C_OK; -eotr: - return ret; -} - -/** - * send one byte in 7bit address mode - * @param data - data to write - * @param stop - ==1 to send stop event - * @return status - */ -i2c_status i2c_7bit_send_onebyte(uint8_t data, uint8_t stop){ - i2c_status ret = i2c_7bit_startw(); - if(ret != I2C_OK){ - I2C1->CR1 |= I2C_CR1_STOP; - goto eotr; - } - I2C1->DR = data; // init data send register - DBG("TxE\n"); - I2C_WAIT(I2C1->SR1 & I2C_SR1_TXE); // wait for TxE (timeout when NACK) - ret = I2C_OK; - DBG("OK\n"); - if(stop){ - I2C_WAIT(I2C1->SR1 & I2C_SR1_BTF); // wait for BTF - DBG("BTF\n"); - } -eotr: - if(stop){ - I2C1->CR1 |= I2C_CR1_STOP; // generate stop event - } - return ret; -} - -// send data array -i2c_status i2c_7bit_send(const uint8_t *data, int datalen){ - i2c_status ret = i2c_7bit_startw(); - if(ret != I2C_OK){ - DBG("NACK!\n"); - I2C1->CR1 |= I2C_CR1_STOP; - goto eotr; - } - for(int i = 0; i < datalen; ++i){ - I2C1->DR = data[i]; - I2C_WAIT(I2C1->SR1 & I2C_SR1_TXE); - } - DBG("GOOD\n"); - ret = I2C_OK; - if(datalen) I2C_WAIT(I2C1->SR1 & I2C_SR1_BTF); -eotr: - I2C1->CR1 |= I2C_CR1_STOP; - return ret; -} - -i2c_status i2c_7bit_receive_onebyte(uint8_t *data, uint8_t stop){ - i2c_status ret = I2C_LINEBUSY; - //I2C_LINEWAIT(); - I2C1->CR1 |= I2C_CR1_START; // generate start sequence - I2C_WAIT(I2C1->SR1 & I2C_SR1_SB); // wait for SB - DBG("Rx SB\n"); - (void) I2C1->SR1; // clear SB - I2C1->DR = addr7r; // set address - DBG("Rx addr\n"); - I2C_WAIT(I2C1->SR1 & I2C_SR1_ADDR); // wait for ADDR flag - DBG("Rx ack\n"); - I2C1->CR1 &= ~I2C_CR1_ACK; // clear ACK - if(I2C1->SR1 & I2C_SR1_AF){ // NACK - DBG("Rx nak\n"); - ret = I2C_NACK; - goto eotr; - } - (void) I2C1->SR2; // clear ADDR - DBG("Rx stop\n"); - if(stop) I2C1->CR1 |= I2C_CR1_STOP; // program STOP - I2C_WAIT(I2C1->SR1 & I2C_SR1_RXNE); // wait for RxNE - DBG("Rx OK\n"); - *data = I2C1->DR; // read data & clear RxNE - ret = I2C_OK; -eotr: - return ret; -} - -i2c_status i2c_7bit_receive_twobytes(uint8_t *data){ - i2c_status ret = I2C_LINEBUSY; - //I2C_LINEWAIT(); - I2C1->CR1 |= I2C_CR1_START | I2C_CR1_POS | I2C_CR1_ACK; // generate start sequence, set pos & ack - I2C_WAIT(I2C1->SR1 & I2C_SR1_SB); // wait for SB - DBG("2 Rx sb\n"); - (void) I2C1->SR1; // clear SB - I2C1->DR = addr7r; // set address - I2C_WAIT(I2C1->SR1 & I2C_SR1_ADDR); // wait for ADDR flag - DBG("2 ADDR\n"); - if(I2C1->SR1 & I2C_SR1_AF){ // NACK - ret = I2C_NACK; - goto eotr; - } - DBG("2 ACK\n"); - (void) I2C1->SR2; // clear ADDR - I2C1->CR1 &= ~I2C_CR1_ACK; // clear ACK - I2C_WAIT(I2C1->SR1 & I2C_SR1_BTF); // wait for BTF - DBG("2 BTF\n"); - I2C1->CR1 |= I2C_CR1_STOP; // program STOP - *data++ = I2C1->DR; *data = I2C1->DR; // read data & clear RxNE - ret = I2C_OK; -eotr: - return ret; -} +// wait for event evt +#define I2C_WAIT(evt) do{ register uint32_t xx = 2000000; \ +while(--xx && !(evt)) IWDG->KR = IWDG_REFRESH; \ + if(!(evt)){ret = I2C_TMOUT; goto eotr;}}while(0) +// wait for !busy +#define I2C_LINEWAIT() do{ register uint32_t xx = 2000000; \ + while(--xx && (I2C1->SR2 & I2C_SR2_BUSY)) IWDG->KR = IWDG_REFRESH; \ + if(I2C1->SR2 & I2C_SR2_BUSY){I2C1->CR1 |= I2C_CR1_SWRST; return I2C_LINEBUSY;}\ +}while(0) -// receive any amount of bytes +static uint8_t bytes_remaining = 0; -i2c_status i2c_7bit_receive(uint8_t *data, uint16_t nbytes){ - if(nbytes == 0) return I2C_HWPROBLEM; - I2C1->SR1 = 0; // clear previous NACK flag & other error flags - if(nbytes == 1) return i2c_7bit_receive_onebyte(data, 1); - else if(nbytes == 2) return i2c_7bit_receive_twobytes(data); - i2c_status ret = I2C_LINEBUSY; - //I2C_LINEWAIT(); - I2C1->CR1 |= I2C_CR1_START | I2C_CR1_ACK; // generate start sequence, set pos & ack - I2C_WAIT(I2C1->SR1 & I2C_SR1_SB); // wait for SB - DBG("got SB\n"); - (void) I2C1->SR1; // clear SB - I2C1->DR = addr7r; // set address - I2C_WAIT(I2C1->SR1 & I2C_SR1_ADDR); // wait for ADDR flag - DBG("send addr\n"); - if(I2C1->SR1 & I2C_SR1_AF){ // NACK - DBG("NACKed\n"); - ret = I2C_NACK; - goto eotr; - } - DBG("ACKed\n"); - (void) I2C1->SR2; // clear ADDR - for(uint16_t x = nbytes - 3; x > 0; --x){ - I2C_WAIT(I2C1->SR1 & I2C_SR1_RXNE); // wait next byte - *data++ = I2C1->DR; // get data - } - DBG("three left\n"); - // three bytes remain to be read - I2C_WAIT(I2C1->SR1 & I2C_SR1_RXNE); // wait dataN-2 - DBG("dataN-2\n"); - I2C_WAIT(I2C1->SR1 & I2C_SR1_BTF); // wait for BTF - DBG("BTF\n"); - I2C1->CR1 &= ~I2C_CR1_ACK; // clear ACK - *data++ = I2C1->DR; // read dataN-2 - I2C1->CR1 |= I2C_CR1_STOP; // program STOP - *data++ = I2C1->DR; // read dataN-1 - I2C_WAIT(I2C1->SR1 & I2C_SR1_RXNE); // wait next byte - *data = I2C1->DR; // read dataN - DBG("got it\n"); - ret = I2C_OK; -eotr: - return ret; -} - -#if 0 i2c_status i2c_start(){ i2c_status ret = I2C_LINEBUSY; + aflag = 44; I2C_LINEWAIT(); - I2C1->CR1 |= I2C_CR1_START | I2C_CR1_ACK; // generate start sequence, set pos & ack + I2C1->CR1 |= I2C_CR1_START; // generate start sequence, set pos & ack + aflag = 1; I2C_WAIT(I2C1->SR1 & I2C_SR1_SB); // wait for SB (void) I2C1->SR1; // clear SB ret = I2C_OK; + aflag = 2; eotr: return ret; } i2c_status i2c_sendaddr(uint8_t addr, uint8_t nread){ - addr <<= 1; - if(nread) addr |= 1; + i2c_set_addr7(addr); i2c_status ret = I2C_LINEBUSY; - I2C1->DR = addr7; // set address + I2C1->DR = (nread) ? addr7r : addr7w; // set address + aflag = 3; I2C_WAIT(I2C1->SR1 & I2C_SR1_ADDR); // wait for ADDR flag + aflag = 4; if(I2C1->SR1 & I2C_SR1_AF){ // NACK ret = I2C_NACK; goto eotr; } + aflag = 5; + ret = I2C_OK; + bytes_remaining = nread; if(nread == 1) I2C1->CR1 &= ~I2C_CR1_ACK; // clear ACK else if(nread >= 2) I2C1->CR1 |= I2C_CR1_ACK; (void) I2C1->SR2; // clear ADDR @@ -268,8 +121,10 @@ eotr: i2c_status i2c_sendbyte(uint8_t data){ i2c_status ret = I2C_LINEBUSY; I2C1->DR = data; // init data send register - DBG("TxE\n"); - I2C_WAIT(I2C1->SR1 & I2C_SR1_TXE); // wait for TxE (timeout when NACK) + //I2C_WAIT(I2C1->SR1 & I2C_SR1_TXE); // wait for TxE (timeout when NACK) + aflag = 6; + I2C_WAIT(I2C1->SR1 & I2C_SR1_BTF); + aflag = 7; ret = I2C_OK; eotr: return ret; @@ -277,10 +132,26 @@ eotr: i2c_status i2c_readbyte(uint8_t *data){ i2c_status ret = I2C_LINEBUSY; + aflag = 8; I2C_WAIT(I2C1->SR1 & I2C_SR1_RXNE); // wait for RxNE + aflag = 9; + if(--bytes_remaining == 1){ + I2C1->CR1 &= ~I2C_CR1_ACK; + I2C1->CR1 |= I2C_CR1_STOP; + } *data = I2C1->DR; // read data & clear RxNE ret = I2C_OK; eotr: return ret; } -#endif + +i2c_status i2c_stop(){ + i2c_status ret = I2C_LINEBUSY; + aflag = 10; + //I2C_WAIT(I2C1->SR1 & (I2C_SR1_TXE | I2C_SR1_BTF)); + //aflag = 11; + I2C1->CR1 |= I2C_CR1_STOP; + ret = I2C_OK; +//eotr: + return ret; +} diff --git a/F1:F103/I2C_tiny/i2c.h b/F1:F103/I2C_tiny/i2c.h index 16ff85f..c817186 100644 --- a/F1:F103/I2C_tiny/i2c.h +++ b/F1:F103/I2C_tiny/i2c.h @@ -31,9 +31,8 @@ typedef enum{ void i2c_setup(); void i2c_set_addr7(uint8_t addr); -i2c_status i2c_7bit_send_onebyte(uint8_t data, uint8_t stop); -i2c_status i2c_7bit_send(const uint8_t *data, int datalen); -i2c_status i2c_7bit_receive_onebyte(uint8_t *data, uint8_t stop); -i2c_status i2c_7bit_receive_twobytes(uint8_t *data); -i2c_status i2c_7bit_receive(uint8_t *data, uint16_t nbytes); - +i2c_status i2c_start(); +i2c_status i2c_sendaddr(uint8_t addr, uint8_t nread); +i2c_status i2c_sendbyte(uint8_t data); +i2c_status i2c_readbyte(uint8_t *data); +i2c_status i2c_stop(); diff --git a/F1:F103/I2C_tiny/usbdev.c b/F1:F103/I2C_tiny/usbdev.c index 52e54e4..d81f588 100644 --- a/F1:F103/I2C_tiny/usbdev.c +++ b/F1:F103/I2C_tiny/usbdev.c @@ -41,27 +41,27 @@ void set_configuration(uint16_t _U_ configuration){ } static void usb_i2c_io(config_pack_t *req, uint8_t *buf, size_t *len){ - static uint8_t iobuf[256] = "1234567890abcdefghijclmnop"; - //uint8_t cmd = req->bRequest; + // static uint8_t iobuf[256] = "1234567890abcdefghijclmnop"; + uint8_t cmd = req->bRequest; uint8_t size = req->wLength; - //i2c_set_addr7(req->wIndex); + uint8_t is_read = req->wValue & I2C_M_RD; i2c_status stat = I2C_NACK; - // ignore NOSTART and STOP! - if(req->wValue & I2C_M_RD){ // read - //stat = i2c_7bit_receive(buf, size); - if(len && *len) memcpy(buf, iobuf, *len); - stat = I2C_OK; - *len = size; - }else{ // write - //stat = i2c_7bit_send(buf, size); - if(len && *len) memcpy(iobuf, buf, *len); - stat = I2C_OK; - *len = 0; + if(cmd & CMD_I2C_BEGIN){ + if(I2C_OK != (stat = i2c_start())) goto eot; + if(I2C_OK != (stat = i2c_sendaddr((uint8_t)req->wIndex, (is_read) ? size : 0))) goto eot; } + for(int i = 0; i < size; ++i){ + if(is_read) stat = i2c_readbyte(buf + i); + else stat = i2c_sendbyte(buf[i]); + if(I2C_OK != stat) goto eot; + } + if(cmd & CMD_I2C_END) stat = i2c_stop(); +eot: if(stat == I2C_OK){ status = STATUS_ADDRESS_ACK; + *len = (is_read) ? size : 0; }else{ - //i2c_setup(); + i2c_setup(); *len = 0; status = STATUS_ADDRESS_NACK; } @@ -77,7 +77,8 @@ void usb_class_request(config_pack_t *req, uint8_t *data, unsigned int datalen){ case CMD_I2C_IO | CMD_I2C_BEGIN: case CMD_I2C_IO | CMD_I2C_END: case CMD_I2C_IO | CMD_I2C_BEGIN | CMD_I2C_END: // write - if(req->wValue & I2C_M_RD) break; + if(req->wValue & I2C_M_RD) break; // OUT - only write + if(!data) break; // wait for data len = datalen; usb_i2c_io(req, data, &len); break; @@ -102,7 +103,7 @@ void usb_class_request(config_pack_t *req, uint8_t *data, unsigned int datalen){ case CMD_I2C_IO | CMD_I2C_BEGIN: case CMD_I2C_IO | CMD_I2C_END: case CMD_I2C_IO | CMD_I2C_BEGIN | CMD_I2C_END: // read - if(req->wValue & I2C_M_RD){ + if(req->wValue & I2C_M_RD){ // IN - only read len = req->wLength; usb_i2c_io(req, buf, &len); } @@ -117,56 +118,8 @@ void usb_class_request(config_pack_t *req, uint8_t *data, unsigned int datalen){ EP_WriteIRQ(0, buf, len); // write ZLP if nothing received } -void usb_vendor_request(config_pack_t *req, uint8_t *data, unsigned int datalen){ - uint8_t buf[USB_EP0BUFSZ]; - size_t len = 0; - //uint8_t recipient = REQUEST_RECIPIENT(req->bmRequestType); - if((req->bmRequestType & 0x80) == 0){ // OUT - setters - switch(req->bRequest){ - case CMD_I2C_IO: - case CMD_I2C_IO | CMD_I2C_BEGIN: - case CMD_I2C_IO | CMD_I2C_END: - case CMD_I2C_IO | CMD_I2C_BEGIN | CMD_I2C_END: // write - if(req->wValue & I2C_M_RD) break; - if(!data || !datalen) break; // omit for next stage - when data received - len = datalen; - usb_i2c_io(req, data, &len); - break; - default: - break; - } - EP_WriteIRQ(0, 0, 0); - return; - } - switch(req->bRequest){ - case CMD_ECHO: - memcpy(buf, &req->wValue, sizeof(req->wValue)); - len = sizeof(req->wValue); - break; - case CMD_GET_FUNC: - /* Report our capabilities */ - bzero(buf, req->wLength); - memcpy(buf, &func, sizeof(func)); - len = req->wLength; - break; - case CMD_I2C_IO: - case CMD_I2C_IO | CMD_I2C_BEGIN: - case CMD_I2C_IO | CMD_I2C_END: - case CMD_I2C_IO | CMD_I2C_BEGIN | CMD_I2C_END: // read - if(req->wValue & I2C_M_RD){ - len = req->wLength; - usb_i2c_io(req, buf, &len); - } - break; - case CMD_GET_STATUS: - memcpy(buf, &status, sizeof(status)); - len = sizeof(status); - break; - default: - break; - } - EP_WriteIRQ(0, buf, len); // write ZLP if nothing received -} +void usb_vendor_request(config_pack_t *req, uint8_t *data, unsigned int datalen) __attribute__ ((alias ("usb_class_request"))); + #if 0 // handler of vendor requests void usb_vendor_request(config_pack_t *req){