Created
July 10, 2021 15:02
-
-
Save S0urceror/83b3b0ce8bbe717f9c78695c932d7f1b to your computer and use it in GitHub Desktop.
CH376s Arduino Code test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "wiring.h" | |
#include "ch376s.h" | |
#include "device.h" | |
#include <stdio.h> | |
#include <string.h> | |
#include "descriptors.h" | |
uint8_t oneOneByte[1] = {1}; | |
uint8_t oneZeroByte[1] = {0}; | |
uint8_t twoZeroBytes[2] = {0,0}; | |
typedef union __attribute__((packed)) _REQUEST_PACK{ | |
unsigned char buffer[64]; | |
struct{ | |
uint8_t bmRequestType; | |
uint8_t bRequest; | |
uint16_t wValue; | |
uint16_t wIndx; | |
uint16_t wLength; | |
}r; | |
} REQUEST_PACKET; | |
typedef union __attribute__((packed)) _UART_PARA | |
{ | |
uint8_t uart_para_buf[ 7 ]; | |
struct | |
{ | |
uint8_t bBaudRate1; // Serial port baud rate (lowest bit) | |
uint8_t bBaudRate2; // (second low) | |
uint8_t bBaudRate3; // (second highest) | |
uint8_t bBaudRate4; // (highest bit) | |
uint8_t bStopBit; // Stop bit | |
uint8_t bParityBit; // Parity bit | |
uint8_t bDataBits; // Number of data bits | |
} uart; | |
} UART_PARA; | |
UART_PARA uart_parameters; | |
void printInterruptName( uint8_t interruptCode) | |
{ | |
const char* name = NULL; | |
switch(interruptCode) | |
{ | |
case USB_INT_BUS_RESET: | |
name = "BUS_RESET"; | |
break; | |
case USB_INT_EP0_SETUP: | |
name = "EP0_SETUP"; | |
break; | |
case USB_INT_EP0_OUT: | |
name = "EP0_OUT"; | |
break; | |
case USB_INT_EP0_IN: | |
name = "EP0_IN"; | |
break; | |
case USB_INT_EP1_OUT: | |
name = "EP1_OUT"; | |
break; | |
case USB_INT_EP1_IN: | |
name = "EP1_IN"; | |
break; | |
case USB_INT_EP2_OUT: | |
name = "EP2_OUT"; | |
break; | |
case USB_INT_EP2_IN: | |
name = "EP2_IN"; | |
break; | |
case USB_INT_USB_SUSPEND: | |
name = "USB_SUSPEND"; | |
break; | |
case USB_INT_WAKE_UP: | |
name = "WAKE_UP"; | |
break; | |
} | |
if(name == NULL) | |
{ | |
printf("Unknown interrupt received: 0x%02X\r\n", interruptCode); | |
} | |
else | |
{ | |
printf("Int: %s\r\n", name); | |
} | |
} | |
uint8_t* dataToTransfer; | |
int dataLength; | |
uint8_t usb_device_address; | |
uint8_t usb_configuration_id; | |
void reset () | |
{ | |
dataLength = 0; | |
dataToTransfer = NULL; | |
usb_device_address = 0; | |
usb_configuration_id = 0; | |
} | |
void sendEP0ACK () | |
{ | |
writeCommand (SET_ENDP3__TX_EP0); | |
writeData (SET_ENDP_ACK); | |
} | |
void sendEP0STALL () | |
{ | |
writeCommand (SET_ENDP3__TX_EP0); | |
writeData (SET_ENDP_STALL); | |
} | |
void writeDataForEndpoint0() | |
{ | |
int amount = min (EP0_PIPE_SIZE,dataLength); | |
// this is a data stage | |
printf(" Writing %d bytes of %d: ", amount,dataLength); | |
writeCommand(CH_CMD_WR_EP0); | |
writeData(amount); | |
for(int i=0; i<amount; i++) | |
{ | |
printf("0x%02X ", dataToTransfer[i]); | |
writeData(dataToTransfer[i]); | |
} | |
printf("\r\n"); | |
dataToTransfer += amount; | |
dataLength -= amount; | |
} | |
size_t read_usb_data (uint8_t* pBuffer) | |
{ | |
uint8_t value = 0; | |
writeCommand(CH375_CMD_RD_USB_DATA); | |
value = readData(); | |
if (value==0) | |
return 0; | |
for (uint8_t i=0;i<value;i++) | |
*(pBuffer+i) = readData(); | |
return value; | |
} | |
void set_target_device_address (uint8_t address) | |
{ | |
writeCommand (CH375_CMD_SET_USB_ADDR); | |
writeData(address); | |
delay (2); | |
} | |
REQUEST_PACKET request; | |
int length; | |
void handleInterrupt () | |
{ | |
// get the type of interrupt | |
writeCommand(CH375_CMD_GET_STATUS); | |
byte interruptType = readData (); | |
if((interruptType & USB_BUS_RESET_MASK) == USB_INT_BUS_RESET) | |
interruptType = USB_INT_BUS_RESET; | |
printInterruptName(interruptType); | |
switch(interruptType) | |
{ | |
case USB_INT_USB_SUSPEND: | |
writeCommand(CH_CMD_ENTER_SLEEP); | |
break; | |
case USB_INT_BUS_RESET: | |
//writeCommand (CH375_CMD_RESET_ALL); | |
reset (); | |
break; | |
// control endpoint setup package | |
case USB_INT_EP0_SETUP: | |
{ | |
// read setup package | |
int length = read_usb_data (request.buffer); | |
printf(" bmRequestType: 0x%02X\r\n", request.r.bmRequestType); | |
printf(" bRequest: %i\r\n", request.r.bRequest); | |
printf(" wValue: 0x%04X\r\n", request.r.wValue); | |
printf(" wIndex: 0x%04X\r\n", request.r.wIndx); | |
printf(" wLength: %03d\r\n", request.r.wLength); | |
// initialize dataLength with length of setup package | |
dataLength = request.r.wLength; | |
if ((request.r.bmRequestType & USB_TYPE_MASK)==USB_TYPE_VENDOR) | |
{ | |
printf("SETUP VENDOR request\r\n"); | |
} | |
if ((request.r.bmRequestType & USB_TYPE_MASK)==USB_TYPE_CLASS) | |
{ | |
printf("SETUP CLASS request\r\n"); | |
switch (request.r.bRequest) // Analyze the class request code and process it | |
{ | |
case SET_LINE_CODING: // SET_LINE_CODING | |
printf (" SET_LINE_CODING\n"); | |
break; | |
case GET_LINE_CODING: // GET_LINE_CODING | |
printf (" GET_LINE_CODING\n"); | |
dataToTransfer = (uint8_t*) &uart_parameters; | |
dataLength = min ((uint16_t) sizeof(UART_PARA),request.r.wLength);; | |
break; | |
case SET_CONTROL_LINE_STATE: // SET_CONTROL_LINE_STATE | |
printf (" SET_CONTROL_LINE_STATE\n"); | |
dataLength = 0; | |
break; | |
default: | |
printf (" Unsupported class command code\n"); | |
sendEP0STALL (); | |
break; | |
} | |
} | |
if ((request.r.bmRequestType & USB_TYPE_MASK)==USB_TYPE_STANDARD) | |
{ | |
printf("SETUP STANDARD request"); | |
if ((request.r.bmRequestType & USB_DIR_MASK) == USB_DIR_IN) // IN | |
{ | |
printf(" IN\r\n"); | |
switch(request.r.bRequest) | |
{ | |
case USB_REQ_GET_DESCRIPTOR: | |
{ | |
printf("USB_REQ_GET_DESCRIPTOR: "); | |
switch (request.r.wValue>>8) | |
{ | |
case USB_DESC_DEVICE: | |
{ | |
printf("DEVICE\r\n"); | |
dataToTransfer = DevDes; | |
dataLength = min ((uint16_t) sizeof(DevDes),request.r.wLength); | |
break; | |
} | |
case USB_DESC_CONFIGURATION: | |
{ | |
printf("CONFIGURATION\r\n"); | |
dataToTransfer = ConDes; | |
dataLength = min ((uint16_t) sizeof(ConDes),request.r.wLength); | |
break; | |
} | |
case USB_DESC_STRING: | |
{ | |
printf("STRING: "); | |
uint8_t stringIndex = request.r.wValue&0xff; | |
switch(stringIndex) | |
{ | |
case 0: | |
{ | |
printf("Language\r\n"); | |
dataToTransfer = LangDes; | |
dataLength = min ((uint16_t) sizeof(LangDes),request.r.wLength); | |
break; | |
} | |
case STRING_DESC_PRODUCT: | |
{ | |
printf("Product\r\n"); | |
dataToTransfer = PRODUCER_Des; | |
dataLength = min ((uint16_t) sizeof(PRODUCER_Des),request.r.wLength); | |
break; | |
} | |
case STRING_DESC_MANUFACTURER: | |
{ | |
printf("Manufacturer\r\n"); | |
dataToTransfer = MANUFACTURER_Des; | |
dataLength = min ((uint16_t) sizeof(MANUFACTURER_Des),request.r.wLength); | |
break; | |
} | |
case STRING_DESC_SERIAL: | |
{ | |
printf("Serial\r\n"); | |
dataToTransfer = PRODUCER_SN_Des; | |
dataLength = min ((uint16_t) sizeof(PRODUCER_SN_Des),request.r.wLength); | |
break; | |
} | |
default: | |
{ | |
printf("Unknown! (%i)\r\n", stringIndex); | |
dataLength = 0; | |
break; | |
} | |
} | |
break; | |
} | |
} | |
writeDataForEndpoint0(); | |
break; | |
} | |
case USB_REQ_GET_CONFIGURATION: | |
printf("USB_REQ_GET_CONFIGURATION\r\n"); | |
dataToTransfer = &usb_configuration_id; | |
dataLength = 1; | |
break; | |
case USB_REQ_GET_INTERFACE: | |
printf("USB_REQ_GET_INTERFACE\r\n"); | |
break; | |
case USB_REQ_GET_STATUS: | |
printf("USB_REQ_GET_STATUS\r\n"); | |
break; | |
default: | |
printf("UNKNOWN IN REQUEST 0x%x\r\n", request.r.bRequest); | |
sendEP0STALL (); | |
break; | |
} | |
} | |
else // OUT | |
{ | |
printf(" OUT\r\n"); | |
switch(request.r.bRequest) | |
{ | |
case USB_REQ_SET_ADDRESS: | |
{ | |
usb_device_address = request.r.wValue; | |
printf(" SET_ADDRESS: %i\r\n", usb_device_address); | |
sendEP0ACK (); | |
break; | |
} | |
case USB_REQ_SET_CONFIGURATION: | |
{ | |
printf(" USB_REQ_SET_CONFIGURATION %d\r\n",request.r.wValue); | |
if (request.r.wValue==USB_CONFIGURATION_ID) | |
usb_configuration_id = request.r.wValue; | |
sendEP0ACK (); | |
break; | |
} | |
case USB_REQ_SET_INTERFACE: | |
{ | |
printf(" USB_REQ_SET_INTERFACE\r\n"); | |
break; | |
} | |
case USB_REQ_CLEAR_FEATURE: | |
{ | |
printf(" USB_REQ_CLEAR_FEATURE\r\n"); | |
break; | |
} | |
default: | |
printf(" UNKNOWN OUT REQUEST 0x%x\r\n", request.r.bRequest); | |
sendEP0STALL (); | |
break; | |
} | |
} | |
} | |
break; | |
} | |
// control endpoint, handles follow-up on setup packets | |
case USB_INT_EP0_IN: | |
{ | |
switch(request.r.bRequest) | |
{ | |
case USB_REQ_SET_ADDRESS: | |
{ | |
printf(" Setting device address to: %d\r\n",usb_device_address); | |
// it's time to set the new address | |
set_target_device_address (usb_device_address); | |
break; | |
} | |
default: | |
{ | |
writeDataForEndpoint0 (); | |
break; | |
} | |
} | |
writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
//writeCommand (CH375_CMD_UNLOCK_USB); | |
break; | |
} | |
case USB_INT_EP0_OUT: | |
{ | |
// absorb any data send to us | |
// | |
// we're not going to do anything | |
length = read_usb_data (request.buffer); | |
printf(" Read %i bytes: ", length); | |
for(int i=0; i<length; i++) | |
{ | |
printf("0x%02X ", request.buffer[i]); | |
} | |
printf("\r\n"); | |
switch(request.r.bRequest) | |
{ | |
case SET_LINE_CODING: | |
{ | |
memcpy (&uart_parameters,request.buffer,length); | |
break; | |
} | |
default: | |
{ | |
break; | |
} | |
} | |
break; | |
} | |
// interrupt endpoint | |
case USB_INT_EP1_IN: | |
printf ("EP1 IN"); | |
break; | |
case USB_INT_EP1_OUT: | |
printf ("EP1 OUT"); | |
break; | |
// bulk endpoint | |
case USB_INT_EP2_IN: | |
printf ("EP2 IN"); | |
break; | |
case USB_INT_EP2_OUT: | |
printf ("EP2 IN"); | |
break; | |
default: | |
sendEP0STALL (); | |
break; | |
} | |
writeCommand (CH375_CMD_UNLOCK_USB); | |
} | |
bool check_exists () | |
{ | |
uint8_t value = 190; | |
uint8_t new_value; | |
//char cmd[] = {0x57,0xAB,CH375_CMD_CHECK_EXIST,value}; | |
writeCommand (CH375_CMD_CHECK_EXIST); | |
writeData(value); | |
new_value = readData (); | |
value = value ^ 255; | |
if (new_value != value) | |
error ("Device does not exist"); | |
} | |
bool set_usb_host_mode (uint8_t mode) | |
{ | |
writeCommand(CH375_CMD_SET_USB_MODE); | |
writeData(mode); | |
uint8_t value; | |
for(int i=0; i!=200; i++ ) | |
{ | |
value = readData(); | |
if ( value == CH_ST_RET_SUCCESS ) | |
return true; | |
delay(1); | |
} | |
return false; | |
} | |
bool initDevice () | |
{ | |
if (!check_exists()) | |
return false; | |
writeCommand (CH375_CMD_RESET_ALL); | |
delay (500); | |
bool result; | |
if (!set_usb_host_mode(CH375_USB_MODE_DEVICE_OUTER_FW)) | |
{ | |
error ("device mode not succeeded"); | |
return false; | |
} | |
printf ("USB device initialized\r\n"); | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment