feat: Add USBIP component (partially completed)
This commit is contained in:
parent
2037ba6392
commit
a15f873744
|
@ -0,0 +1,320 @@
|
|||
/**
|
||||
* @file usb_defs.h
|
||||
* @brief Modify
|
||||
* @version 0.1
|
||||
* @date 2020-01-22
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
*/
|
||||
|
||||
//
|
||||
// Created by thevoidnn on 10/25/17.
|
||||
//
|
||||
|
||||
#ifndef __USB_DEFS_H__
|
||||
#define __USB_DEFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#define USB_CLASS_MISCELLANEOUS_DEVICE 0xef
|
||||
#define USB_MISC_SUBCLASS_COMMON 0x02
|
||||
#define USB_MISC_PROTOCOL_INTERFACE_ASSOCIATION_DESCRIPTOR 0x01
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
union word_t {
|
||||
struct {
|
||||
uint8_t u8lo;
|
||||
uint8_t u8hi;
|
||||
} __attribute__((packed));
|
||||
uint16_t u16;
|
||||
};
|
||||
|
||||
struct usb_standard_request
|
||||
{
|
||||
uint8_t bmRequestType;
|
||||
uint8_t bRequest;
|
||||
word_t wValue;
|
||||
word_t wIndex;
|
||||
word_t wLength;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//#define USB_CLASS_HID 3
|
||||
|
||||
#define USB_DT_HID 0x21
|
||||
#define USB_DT_REPORT 0x22
|
||||
|
||||
//struct usb_hid_descriptor {
|
||||
// uint8_t bLength;
|
||||
// uint8_t bDescriptorType;
|
||||
// uint16_t bcdHID;
|
||||
// uint8_t bCountryCode;
|
||||
// uint8_t bNumDescriptors;
|
||||
//} __attribute__((packed));
|
||||
//#define USB_DT_HID_SIZE sizeof(struct usb_hid_descriptor)
|
||||
|
||||
//struct usb_hid_report_descriptor {
|
||||
// uint8_t bDescriptorType;
|
||||
// uint16_t wReportLength;
|
||||
//} __attribute__((packed));
|
||||
|
||||
|
||||
#define USB_DT_REPORT_SIZE sizeof(struct usb_hid_report_descriptor)
|
||||
|
||||
|
||||
/* Class Definition */
|
||||
#define USB_CLASS_VENDOR 0xFF
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* Table 9-2. Format of Setup Data */
|
||||
/* bmRequestType bit definitions */
|
||||
|
||||
/* bit 7 : Direction */
|
||||
#define USB_REQ_TYPE_OUT 0x00 // Host-to-device
|
||||
#define USB_REQ_TYPE_IN 0x80 // Device-to-host
|
||||
/* bits 6..5 : Type */
|
||||
#define USB_REQ_TYPE_STANDARD 0x00
|
||||
#define USB_REQ_TYPE_CLASS 0x20
|
||||
#define USB_REQ_TYPE_VENDOR 0x40
|
||||
#define USB_REQ_TYPE_RESERVED 0x60
|
||||
/* bits 4..0 : Recipient */
|
||||
#define USB_REQ_TYPE_DEVICE 0x00
|
||||
#define USB_REQ_TYPE_INTERFACE 0x01
|
||||
#define USB_REQ_TYPE_ENDPOINT 0x02
|
||||
#define USB_REQ_TYPE_OTHER 0x03
|
||||
#define USB_REQ_TYPE_RESERVED 0x1F
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Request Codes - Table 9-4 */
|
||||
#define USB_REQ_GET_STATUS 0
|
||||
#define USB_REQ_CLEAR_FEATURE 1
|
||||
/* Reserved for future use: 2 */
|
||||
#define USB_REQ_SET_FEATURE 3
|
||||
/* Reserved for future use: 3 */
|
||||
#define USB_REQ_SET_ADDRESS 5
|
||||
#define USB_REQ_GET_DESCRIPTOR 6
|
||||
#define USB_REQ_SET_DESCRIPTOR 7
|
||||
#define USB_REQ_GET_CONFIGURATION 8
|
||||
#define USB_REQ_SET_CONFIGURATION 9
|
||||
#define USB_REQ_GET_INTERFACE 10
|
||||
#define USB_REQ_SET_INTERFACE 11
|
||||
#define USB_REQ_SET_SYNCH_FRAME 12
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Descriptor Types - Table 9-5 */
|
||||
#define USB_DT_DEVICE 1
|
||||
#define USB_DT_CONFIGURATION 2
|
||||
#define USB_DT_STRING 3
|
||||
#define USB_DT_INTERFACE 4
|
||||
#define USB_DT_ENDPOINT 5
|
||||
#define USB_DT_DEVICE_QUALIFIER 6
|
||||
#define USB_DT_OTHER_SPEED_CONFIGURATION 7
|
||||
#define USB_DT_INTERFACE_POWER 8
|
||||
/* From ECNs */
|
||||
#define USB_DT_OTG 9
|
||||
#define USB_DT_DEBUG 10
|
||||
#define USB_DT_INTERFACE_ASSOCIATION 11
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Feature Selectors - Table 9-6 */
|
||||
#define USB_FEAT_ENDPOINT_HALT 0 // Recipient: Device
|
||||
#define USB_FEAT_DEVICE_REMOTE_WAKEUP 1 // Recipient: Endpoint
|
||||
#define USB_FEAT_TEST_MODE 2 // Recipient: Device
|
||||
|
||||
/* Information Returned by a GetStatus() Request to a Device - Figure 9-4 */
|
||||
#define USB_DEV_STATUS_SELF_POWERED 0x01
|
||||
#define USB_DEV_STATUS_REMOTE_WAKEUP 0x02
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Device Descriptor - Table 9-8 */
|
||||
struct usb_device_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
uint8_t iManufacturer;
|
||||
uint8_t iProduct;
|
||||
uint8_t iSerialNumber;
|
||||
uint8_t bNumConfigurations;
|
||||
} __attribute__((packed));
|
||||
#define USB_DT_DEVICE_SIZE sizeof(struct usb_device_descriptor)
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Device_Qualifier Descriptor - Table 9-9
|
||||
* Not used in this implementation.
|
||||
*/
|
||||
struct usb_device_qualifier_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t bcdUSB;
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
uint8_t bMaxPacketSize0;
|
||||
uint8_t bNumConfigurations;
|
||||
uint8_t bReserved;
|
||||
} __attribute__((packed));
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/* This is only defined as a top level named struct to improve c++
|
||||
* compatibility. You should never need to instance this struct
|
||||
* in user code! */
|
||||
struct usb_interface {
|
||||
uint8_t *cur_altsetting;
|
||||
uint8_t num_altsetting;
|
||||
const struct usb_iface_assoc_descriptor *iface_assoc;
|
||||
const struct usb_interface_descriptor *altsetting;
|
||||
};
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Configuration Descriptor - Table 9-10 */
|
||||
struct usb_config_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wTotalLength;
|
||||
uint8_t bNumInterfaces;
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t iConfiguration;
|
||||
uint8_t bmAttributes;
|
||||
uint8_t bMaxPower;
|
||||
} __attribute__((packed));
|
||||
#define USB_DT_CONFIGURATION_SIZE sizeof(struct usb_config_descriptor)
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
/* USB Configuration Descriptor *bmAttributes* bit definitions */
|
||||
#define USB_CONFIG_ATTR_DEFAULT 0x80 /** always required (USB2.0 table 9-10) */
|
||||
#define USB_CONFIG_ATTR_SELF_POWERED 0x40
|
||||
#define USB_CONFIG_ATTR_REMOTE_WAKEUP 0x20
|
||||
|
||||
/* Other Speed Configuration is the same as Configuration Descriptor.
|
||||
* - Table 9-11
|
||||
*/
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Interface Descriptor - Table 9-12 */
|
||||
struct usb_interface_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bInterfaceNumber;
|
||||
uint8_t bAlternateSetting;
|
||||
uint8_t bNumEndpoints;
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t iInterface;
|
||||
} __attribute__((packed));
|
||||
#define USB_DT_INTERFACE_SIZE sizeof(struct usb_interface_descriptor)
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Standard Endpoint Descriptor - Table 9-13 */
|
||||
struct usb_endpoint_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bEndpointAddress;
|
||||
uint8_t bmAttributes;
|
||||
uint16_t wMaxPacketSize;
|
||||
uint8_t bInterval;
|
||||
} __attribute__((packed));
|
||||
#define USB_DT_ENDPOINT_SIZE sizeof(struct usb_endpoint_descriptor)
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
/* USB bEndpointAddress helper macros */
|
||||
#define USB_ENDPOINT_ADDR_OUT(x) (x)
|
||||
#define USB_ENDPOINT_ADDR_IN(x) (0x80 | (x))
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* USB Endpoint Descriptor bmAttributes bit definitions - Table 9-13 */
|
||||
/* bits 1..0 : Transfer type */
|
||||
#define USB_ENDPOINT_ATTR_CONTROL 0x00
|
||||
#define USB_ENDPOINT_ATTR_ISOCHRONOUS 0x01
|
||||
#define USB_ENDPOINT_ATTR_BULK 0x02
|
||||
#define USB_ENDPOINT_ATTR_INTERRUPT 0x03
|
||||
#define USB_ENDPOINT_ATTR_TYPE 0x03
|
||||
// If not an isochronous endpoint, bits 5..2 are reserved
|
||||
// and must be set to zero.
|
||||
/* bits 3..2 : Sync type (only if ISOCHRONOUS) */
|
||||
#define USB_ENDPOINT_ATTR_NOSYNC 0x00
|
||||
#define USB_ENDPOINT_ATTR_ASYNC 0x04
|
||||
#define USB_ENDPOINT_ATTR_ADAPTIVE 0x08
|
||||
#define USB_ENDPOINT_ATTR_SYNC 0x0C
|
||||
#define USB_ENDPOINT_ATTR_SYNCTYPE 0x0C
|
||||
/* bits 5..4 : Usage type (only if ISOCHRONOUS) */
|
||||
#define USB_ENDPOINT_ATTR_DATA 0x00
|
||||
#define USB_ENDPOINT_ATTR_FEEDBACK 0x10
|
||||
#define USB_ENDPOINT_ATTR_IMPLICIT_FEEDBACK_DATA 0x20
|
||||
#define USB_ENDPOINT_ATTR_USAGETYPE 0x30
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
/* Table 9-15 specifies String Descriptor Zero.
|
||||
* Table 9-16 specified UNICODE String Descriptor.
|
||||
*/
|
||||
struct usb_string_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint16_t wData[];
|
||||
} __attribute__((packed));
|
||||
|
||||
/* From ECN: Interface Association Descriptors, Table 9-Z */
|
||||
struct usb_iface_assoc_descriptor {
|
||||
uint8_t bLength;
|
||||
uint8_t bDescriptorType;
|
||||
uint8_t bFirstInterface;
|
||||
uint8_t bInterfaceCount;
|
||||
uint8_t bFunctionClass;
|
||||
uint8_t bFunctionSubClass;
|
||||
uint8_t bFunctionProtocol;
|
||||
uint8_t iFunction;
|
||||
} __attribute__((packed));
|
||||
#define USB_DT_INTERFACE_ASSOCIATION_SIZE \
|
||||
sizeof(struct usb_iface_assoc_descriptor)
|
||||
|
||||
enum usb_language_id {
|
||||
USB_LANGID_ENGLISH_US = 0x409,
|
||||
};
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,223 @@
|
|||
/**
|
||||
* @file usbip_defs.h
|
||||
* @brief Simple modification
|
||||
* @version 0.1
|
||||
* @date 2020-01-22
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
*/
|
||||
|
||||
// Focus on the following structures in this file:
|
||||
// usbip_stage2_header
|
||||
// usbip_stage1_response_devlist
|
||||
|
||||
|
||||
//
|
||||
// Created by thevoidnn on 10/25/17.
|
||||
//
|
||||
|
||||
#ifndef __USBIP_DEFS_H__
|
||||
#define __USBIP_DEFS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "usb_defs.h"
|
||||
|
||||
#define USBIP_SYSFS_PATH_SIZE 256
|
||||
#define USBIP_BUSID_SIZE 32
|
||||
|
||||
enum usbip_stage1_command {
|
||||
// Offset 2
|
||||
USBIP_STAGE1_CMD_DEVICE_LIST = 0x05, // OP_REQ_DEVLIST
|
||||
USBIP_STAGE1_CMD_DEVICE_ATTACH = 0x03, // OP_REQ_IMPORT
|
||||
};
|
||||
|
||||
enum usbip_stager2_command { ////TODO: change to stage2
|
||||
//Offset 0
|
||||
USBIP_STAGE2_REQ_SUBMIT = 0x0001,
|
||||
USBIP_STAGE2_REQ_UNLINK = 0x0002,
|
||||
USBIP_STAGE2_RSP_SUBMIT = 0x0003,
|
||||
USBIP_STAGE2_RSP_UNLINK = 0x0004,
|
||||
};
|
||||
|
||||
enum usbip_stage2_direction {
|
||||
USBIP_DIR_OUT = 0x00,
|
||||
USBIP_DIR_IN = 0x01,
|
||||
};
|
||||
|
||||
struct usbip_stage1_header {
|
||||
uint16_t version;
|
||||
uint16_t command;
|
||||
uint32_t status;
|
||||
} __attribute__ ((__packed__));
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
// Device description
|
||||
struct usbip_stage1_usb_device {
|
||||
char path[USBIP_SYSFS_PATH_SIZE];
|
||||
char busid[USBIP_BUSID_SIZE];
|
||||
|
||||
uint32_t busnum;
|
||||
uint32_t devnum;
|
||||
uint32_t speed;
|
||||
|
||||
uint16_t idVendor;
|
||||
uint16_t idProduct;
|
||||
uint16_t bcdDevice;
|
||||
|
||||
uint8_t bDeviceClass;
|
||||
uint8_t bDeviceSubClass;
|
||||
uint8_t bDeviceProtocol;
|
||||
|
||||
uint8_t bConfigurationValue;
|
||||
uint8_t bNumConfigurations;
|
||||
uint8_t bNumInterfaces;
|
||||
} __attribute__((packed));
|
||||
|
||||
// Interface description
|
||||
struct usbip_stage1_usb_interface {
|
||||
uint8_t bInterfaceClass;
|
||||
uint8_t bInterfaceSubClass;
|
||||
uint8_t bInterfaceProtocol;
|
||||
uint8_t padding;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
|
||||
struct usbip_stage1_response_devlist_entry {
|
||||
struct usbip_stage1_usb_device udev;
|
||||
struct usbip_stage1_usb_interface uinf[];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct usbip_stage1_response_devlist {
|
||||
uint32_t list_size;
|
||||
usbip_stage1_response_devlist_entry devices[];
|
||||
} __attribute__ ((__packed__));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct usbip_header_basic - data pertinent to every URB request
|
||||
* RESPONSE & REQUEST
|
||||
*
|
||||
* @command: the usbip request type
|
||||
* @seqnum: sequential number that identifies requests; incremented per
|
||||
* connection
|
||||
* @devid: specifies a remote USB device uniquely instead of busnum and devnum;
|
||||
* in the stub driver, this value is ((busnum << 16) | devnum)
|
||||
* @direction: direction of the transfer
|
||||
* @ep: endpoint number
|
||||
*/
|
||||
struct usbip_stage2_header_basic {
|
||||
uint32_t command;
|
||||
uint32_t seqnum;
|
||||
uint32_t devid;
|
||||
uint32_t direction;
|
||||
uint32_t ep;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct usbip_header_cmd_submit - USBIP_CMD_SUBMIT packet header
|
||||
* >>>REQUEST
|
||||
*
|
||||
* @transfer_flags: URB flags
|
||||
* @transfer_buffer_length: the data size for (in) or (out) transfer
|
||||
* @start_frame: initial frame for isochronous or interrupt transfers
|
||||
* @number_of_packets: number of isochronous packets
|
||||
* @interval: maximum time for the request on the server-side host controller
|
||||
* @setup: setup data for a control request
|
||||
*/
|
||||
struct usbip_stage2_header_cmd_submit {
|
||||
uint32_t transfer_flags;
|
||||
int32_t data_length;
|
||||
|
||||
/* it is difficult for usbip to sync frames (reserved only?) */
|
||||
int32_t start_frame;
|
||||
int32_t number_of_packets;
|
||||
int32_t interval;
|
||||
|
||||
union {
|
||||
uint8_t setup[8];
|
||||
usb_standard_request request;
|
||||
};
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct usbip_header_ret_submit - USBIP_RET_SUBMIT packet header
|
||||
* <<<RESPONSE
|
||||
*
|
||||
* @status: return status of a non-iso request
|
||||
* @actual_length: number of bytes transferred
|
||||
* @start_frame: initial frame for isochronous or interrupt transfers
|
||||
* @number_of_packets: number of isochronous packets
|
||||
* @error_count: number of errors for isochronous transfers
|
||||
*/
|
||||
struct usbip_stage2_header_ret_submit {
|
||||
int32_t status;
|
||||
int32_t data_length;
|
||||
int32_t start_frame;
|
||||
int32_t number_of_packets;
|
||||
int32_t error_count;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct usbip_header_cmd_unlink - USBIP_CMD_UNLINK packet header
|
||||
* >>>REQUEST
|
||||
* @seqnum: the URB seqnum to unlink
|
||||
*/
|
||||
struct usbip_stage2_header_cmd_unlink {
|
||||
uint32_t seqnum;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* struct usbip_header_ret_unlink - USBIP_RET_UNLINK packet header
|
||||
* <<<RESPONSE
|
||||
* @status: return status of the request
|
||||
*/
|
||||
struct usbip_stage2_header_ret_unlink {
|
||||
int32_t status;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* struct usbip_header - common header for all usbip packets
|
||||
* @base: the basic header
|
||||
* @u: packet type dependent header
|
||||
*/
|
||||
struct usbip_stage2_header {
|
||||
struct usbip_stage2_header_basic base;
|
||||
|
||||
union {
|
||||
struct usbip_stage2_header_cmd_submit cmd_submit;
|
||||
struct usbip_stage2_header_ret_submit ret_submit;
|
||||
struct usbip_stage2_header_cmd_unlink cmd_unlink;
|
||||
struct usbip_stage2_header_ret_unlink ret_unlink;
|
||||
} u;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -1,4 +1,4 @@
|
|||
set(COMPONENT_SRCS "tcp_server.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ". $ENV{IDF_PATH}/components/esp8266/include/esp8266/")
|
||||
set(COMPONENT_SRCS "main.c timer.c tcp_server.c usbip_server.c")
|
||||
set(COMPONENT_ADD_INCLUDEDIRS ". $ENV{IDF_PATH}/components/esp8266/include/esp8266/ ../components/USBIP")
|
||||
|
||||
register_component()
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
#
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
147
main/main.c
147
main/main.c
|
@ -23,20 +23,16 @@
|
|||
#include "lwip/sys.h"
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
#include "gpio.h"
|
||||
#include "hw_timer.h"
|
||||
#include "timer_struct.h"
|
||||
|
||||
#include "tcp_server.h"
|
||||
#include "timer.h"
|
||||
#include "wifi_configuration.h"
|
||||
|
||||
/* The examples use simple WiFi configuration that you can set via
|
||||
'make menuconfig'.
|
||||
If you'd rather not, just change the below entries to strings with
|
||||
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
|
||||
*/
|
||||
#define EXAMPLE_WIFI_SSID "DAP"
|
||||
#define EXAMPLE_WIFI_PASS "12345678"
|
||||
|
||||
#define PORT 22350
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected & ready to make a request */
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
|
@ -46,7 +42,6 @@ const int IPV4_GOTIP_BIT = BIT0;
|
|||
const int IPV6_GOTIP_BIT = BIT1;
|
||||
#endif
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
static esp_err_t event_handler(void *ctx, system_event_t *event)
|
||||
{
|
||||
|
@ -130,143 +125,9 @@ static void wait_for_ip()
|
|||
os_printf("Connected to AP");
|
||||
}
|
||||
|
||||
static void tcp_server_task(void *pvParameters)
|
||||
{
|
||||
char rx_buffer[2048];
|
||||
char addr_str[128];
|
||||
int addr_family;
|
||||
int ip_protocol;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_IPV4
|
||||
struct sockaddr_in destAddr;
|
||||
destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
destAddr.sin_family = AF_INET;
|
||||
destAddr.sin_port = htons(PORT);
|
||||
addr_family = AF_INET;
|
||||
ip_protocol = IPPROTO_IP;
|
||||
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#else // IPV6
|
||||
struct sockaddr_in6 destAddr;
|
||||
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
|
||||
destAddr.sin6_family = AF_INET6;
|
||||
destAddr.sin6_port = htons(PORT);
|
||||
addr_family = AF_INET6;
|
||||
ip_protocol = IPPROTO_IPV6;
|
||||
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#endif
|
||||
|
||||
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
||||
if (listen_sock < 0)
|
||||
{
|
||||
os_printf("Unable to create socket: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket created");
|
||||
|
||||
int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
|
||||
if (err != 0)
|
||||
{
|
||||
os_printf("Socket unable to bind: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket binded");
|
||||
|
||||
err = listen(listen_sock, 1);
|
||||
if (err != 0)
|
||||
{
|
||||
os_printf("Error occured during listen: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket listening");
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_IPV6
|
||||
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
|
||||
#else
|
||||
struct sockaddr_in sourceAddr;
|
||||
#endif
|
||||
uint32_t addrLen = sizeof(sourceAddr);
|
||||
int sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
|
||||
if (sock < 0)
|
||||
{
|
||||
os_printf("Unable to accept connection: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket accepted");
|
||||
|
||||
while (1)
|
||||
{
|
||||
int len = recv(sock, rx_buffer, 2047, 0);
|
||||
// Error occured during receiving
|
||||
if (len < 0)
|
||||
{
|
||||
os_printf("recv failed: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
// Connection closed
|
||||
else if (len == 0)
|
||||
{
|
||||
os_printf("Connection closed\r\n");
|
||||
break;
|
||||
}
|
||||
// Data received
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLE_IPV6
|
||||
// Get the sender's ip address as string
|
||||
if (sourceAddr.sin6_family == PF_INET)
|
||||
{
|
||||
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
|
||||
}
|
||||
else if (sourceAddr.sin6_family == PF_INET6)
|
||||
{
|
||||
inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
|
||||
}
|
||||
#else
|
||||
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#endif
|
||||
|
||||
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
|
||||
//os_printf("Received %d bytes from %s:\r\n", len, addr_str);
|
||||
// os_printf("%s", rx_buffer);
|
||||
|
||||
int err = send(sock, rx_buffer, len, 0);
|
||||
if (err < 0)
|
||||
{
|
||||
os_printf("Error occured during sending: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sock != -1)
|
||||
{
|
||||
os_printf("Shutting down socket and restarting...\r\n");
|
||||
shutdown(sock, 0);
|
||||
close(sock);
|
||||
|
||||
shutdown(listen_sock, 0);
|
||||
close(listen_sock);
|
||||
vTaskDelay(5);
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void timer_create_task()
|
||||
{
|
||||
// FRC1 frequency 80MHz
|
||||
vPortEnterCritical();
|
||||
frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz
|
||||
frc1.ctrl.intr_type = TIMER_EDGE_INT;
|
||||
frc1.ctrl.reload = 0x01;
|
||||
frc1.load.data = 0x1000000U - 1U;
|
||||
frc1.ctrl.en = 0x01;
|
||||
vPortExitCritical();
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
|
@ -274,6 +135,6 @@ void app_main()
|
|||
initialise_wifi();
|
||||
wait_for_ip();
|
||||
|
||||
xTaskCreate(timer_create_task, "timer_create", 2048, NULL, 10, NULL);
|
||||
xTaskCreate(timer_create_task, "timer_create", 1024, NULL, 10, NULL);
|
||||
xTaskCreate(tcp_server_task, "tcp_server", 4096, NULL, 5, NULL);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* @file tcp_server.c
|
||||
* @brief Handle main tcp tasks
|
||||
* @version 0.1
|
||||
* @date 2020-01-22
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
*/
|
||||
#include "tcp_server.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/param.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event_loop.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
#include "wifi_configuration.h"
|
||||
#include "usbip_server.h"
|
||||
|
||||
uint8_t state = ACCEPTING;
|
||||
int sock = -1;
|
||||
void tcp_server_task(void *pvParameters)
|
||||
{
|
||||
char rx_buffer[2048];
|
||||
char addr_str[128];
|
||||
int addr_family;
|
||||
int ip_protocol;
|
||||
|
||||
while (1)
|
||||
{
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_IPV4
|
||||
struct sockaddr_in destAddr;
|
||||
destAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
destAddr.sin_family = AF_INET;
|
||||
destAddr.sin_port = htons(PORT);
|
||||
addr_family = AF_INET;
|
||||
ip_protocol = IPPROTO_IP;
|
||||
inet_ntoa_r(destAddr.sin_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#else // IPV6
|
||||
struct sockaddr_in6 destAddr;
|
||||
bzero(&destAddr.sin6_addr.un, sizeof(destAddr.sin6_addr.un));
|
||||
destAddr.sin6_family = AF_INET6;
|
||||
destAddr.sin6_port = htons(PORT);
|
||||
addr_family = AF_INET6;
|
||||
ip_protocol = IPPROTO_IPV6;
|
||||
inet6_ntoa_r(destAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#endif
|
||||
|
||||
int listen_sock = socket(addr_family, SOCK_STREAM, ip_protocol);
|
||||
if (listen_sock < 0)
|
||||
{
|
||||
os_printf("Unable to create socket: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket created");
|
||||
|
||||
int err = bind(listen_sock, (struct sockaddr *)&destAddr, sizeof(destAddr));
|
||||
if (err != 0)
|
||||
{
|
||||
os_printf("Socket unable to bind: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket binded");
|
||||
|
||||
err = listen(listen_sock, 1);
|
||||
if (err != 0)
|
||||
{
|
||||
os_printf("Error occured during listen: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket listening");
|
||||
|
||||
#ifdef CONFIG_EXAMPLE_IPV6
|
||||
struct sockaddr_in6 sourceAddr; // Large enough for both IPv4 or IPv6
|
||||
#else
|
||||
struct sockaddr_in sourceAddr;
|
||||
#endif
|
||||
uint32_t addrLen = sizeof(sourceAddr);
|
||||
sock = accept(listen_sock, (struct sockaddr *)&sourceAddr, &addrLen);
|
||||
if (sock < 0)
|
||||
{
|
||||
os_printf("Unable to accept connection: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
os_printf("Socket accepted");
|
||||
|
||||
while (1)
|
||||
{
|
||||
int len = recv(sock, rx_buffer, 2047, 0);
|
||||
// Error occured during receiving
|
||||
if (len < 0)
|
||||
{
|
||||
os_printf("recv failed: errno %d\r\n", errno);
|
||||
break;
|
||||
}
|
||||
// Connection closed
|
||||
else if (len == 0)
|
||||
{
|
||||
os_printf("Connection closed\r\n");
|
||||
break;
|
||||
}
|
||||
// Data received
|
||||
else
|
||||
{
|
||||
#ifdef CONFIG_EXAMPLE_IPV6
|
||||
// Get the sender's ip address as string
|
||||
if (sourceAddr.sin6_family == PF_INET)
|
||||
{
|
||||
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
|
||||
}
|
||||
else if (sourceAddr.sin6_family == PF_INET6)
|
||||
{
|
||||
inet6_ntoa_r(sourceAddr.sin6_addr, addr_str, sizeof(addr_str) - 1);
|
||||
}
|
||||
#else
|
||||
inet_ntoa_r(((struct sockaddr_in *)&sourceAddr)->sin_addr.s_addr, addr_str, sizeof(addr_str) - 1);
|
||||
#endif
|
||||
|
||||
rx_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
|
||||
//os_printf("Received %d bytes from %s:\r\n", len, addr_str);
|
||||
// os_printf("%s", rx_buffer);
|
||||
switch (state)
|
||||
{
|
||||
case ACCEPTING:
|
||||
state = ATTACHING;
|
||||
break;
|
||||
|
||||
case ATTACHING:
|
||||
attach(rx_buffer, len);
|
||||
break;
|
||||
|
||||
case EMULATING:
|
||||
emulate(rx_buffer, len);
|
||||
break;
|
||||
}
|
||||
|
||||
// int err = send(sock, rx_buffer, len, 0);
|
||||
// if (err < 0)
|
||||
// {
|
||||
// os_printf("Error occured during sending: errno %d\r\n", errno);
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
}
|
||||
state = ACCEPTING;
|
||||
if (sock != -1)
|
||||
{
|
||||
os_printf("Shutting down socket and restarting...\r\n");
|
||||
shutdown(sock, 0);
|
||||
close(sock);
|
||||
|
||||
shutdown(listen_sock, 0);
|
||||
close(listen_sock);
|
||||
vTaskDelay(5);
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __TCP_SERVER_H__
|
||||
#define __TCP_SERVER_H__
|
||||
|
||||
void tcp_server_task(void *pvParameters);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @file timer.c
|
||||
* @brief Hardware timer for DAP timestamp
|
||||
* @version 0.1
|
||||
* @date 2020-01-22
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "timer.h"
|
||||
#include "hw_timer.h"
|
||||
#include "timer_struct.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
void timer_create_task()
|
||||
{
|
||||
// FRC1 frequency 80MHz
|
||||
vPortEnterCritical();
|
||||
frc1.ctrl.div = TIMER_CLKDIV_16; // 80MHz / 16 = 5MHz
|
||||
frc1.ctrl.intr_type = TIMER_EDGE_INT;
|
||||
frc1.ctrl.reload = 0x01;
|
||||
frc1.load.data = 0x1000000U - 1U;
|
||||
frc1.ctrl.en = 0x01;
|
||||
vPortExitCritical();
|
||||
vTaskDelete(NULL);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __TIMER_H__
|
||||
#define __TIMER_H__
|
||||
|
||||
void timer_create_task();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,132 @@
|
|||
#include <stdint.h>
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/sys.h"
|
||||
#include <lwip/netdb.h>
|
||||
|
||||
#include "usbip_server.h"
|
||||
#include "usbip_defs.h"
|
||||
#include "usb_defs.h"
|
||||
|
||||
static int read_stage1_command(uint8_t *buffer, uint32_t length);
|
||||
static int handle_device_list(uint8_t *buffer, uint32_t length);
|
||||
static int handle_device_attach(uint8_t *buffer, uint32_t length);
|
||||
static void send_stage1_header(uint16_t command, uint32_t status);
|
||||
static void send_device_list();
|
||||
static void send_device_info();
|
||||
|
||||
|
||||
|
||||
int attach(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
uint32_t command = read_stage1_command(buffer, length);
|
||||
if (command < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (command)
|
||||
{
|
||||
case USBIP_STAGE1_CMD_DEVICE_LIST: // OP_REQ_DEVLIST
|
||||
handle_device_list(buffer, length);
|
||||
break;
|
||||
|
||||
case USBIP_STAGE1_CMD_DEVICE_ATTACH: // OP_REQ_IMPORT
|
||||
handle_device_attach(buffer, length);
|
||||
break;
|
||||
|
||||
default:
|
||||
os_printf("s1 unknown command: %d\r\n", command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int read_stage1_command(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
if (length < sizeof(usbip_stage1_header))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
usbip_stage1_header *req = (usbip_stage1_header *)buffer;
|
||||
return ntohs(req->command) & 0xFF; // 0x80xx low bit
|
||||
}
|
||||
|
||||
static int handle_device_list(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
os_printf("Handling dev list request...\r\n");
|
||||
send_stage1_header(USBIP_STAGE1_CMD_DEVICE_LIST, 0);
|
||||
send_device_list();
|
||||
}
|
||||
|
||||
static int handle_device_attach(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
int
|
||||
}
|
||||
|
||||
static void send_stage1_header(uint16_t command, uint32_t status)
|
||||
{
|
||||
os_printf("Sending header...\r\n");
|
||||
usbip_stage1_header header;
|
||||
header.version = htons(273); // 273???
|
||||
header.command = htons(command);
|
||||
header.status = htonl(status);
|
||||
|
||||
send(socket, (uint8_t *)&header, sizeof(usbip_stage1_header), 0);
|
||||
}
|
||||
|
||||
static void send_device_list()
|
||||
{
|
||||
os_printf("Sending device list...\r\n");
|
||||
|
||||
// send device list size:
|
||||
os_printf("Sending device list size...\r\n");
|
||||
usbip_stage1_response_devlist response_devlist;
|
||||
|
||||
// we have only 1 device, so:
|
||||
response_devlist.list_size = htonl(1);
|
||||
|
||||
send(socket, (uint8_t *)&response_devlist, sizeof(usbip_stage1_response_devlist), 0);
|
||||
|
||||
// may be foreach:
|
||||
|
||||
{
|
||||
// send device info:
|
||||
send_device_info();
|
||||
// send device interfaces: // (1)
|
||||
send_interface_info();
|
||||
}
|
||||
}
|
||||
|
||||
void send_device_info()
|
||||
{
|
||||
//// TODO:fill this
|
||||
os_printf("Sending device info...");
|
||||
usbip_stage1_usb_device device;
|
||||
|
||||
strcpy(device.path, "/sys/devices/pci0000:00/0000:00:01.2/usb1/1-1");
|
||||
strcpy(device.busid, "1-1");
|
||||
|
||||
device.busnum = htonl(1);
|
||||
device.devnum = htonl(2);
|
||||
device.speed = htonl(2); // what is this???
|
||||
//// TODO: 0200H for USB2.0
|
||||
|
||||
//// TODO: fill Vendor Product Device-version
|
||||
device.idVendor = htons(USB_DEVICE_VENDOR_ID);
|
||||
device.idProduct = htons(USB_DEVICE_PRODUCT_ID);
|
||||
device.bcdDevice = htons(USB_DEVICE_VERSION);
|
||||
|
||||
device.bDeviceClass = 0x00; // <defined at interface level>
|
||||
device.bDeviceSubClass = 0x00;
|
||||
device.bDeviceProtocol = 0x00;
|
||||
|
||||
device.bConfigurationValue = 1;
|
||||
device.bNumConfigurations = 1;
|
||||
device.bNumInterfaces = 1;
|
||||
|
||||
write(&device, sizeof(usbip_stage1_usb_device));
|
||||
}
|
||||
|
||||
int emulate(uint8_t *buffer, uint32_t length)
|
||||
{
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef __USBIP_SERVER_H__
|
||||
#define __USBIP_SERVER_H__
|
||||
#include <stdint.h>
|
||||
enum state_t
|
||||
{
|
||||
ACCEPTING,
|
||||
ATTACHING,
|
||||
EMULATING
|
||||
};
|
||||
extern uint32_t state;
|
||||
extern int socket;
|
||||
|
||||
int attach(uint8_t *buffer, uint32_t length);
|
||||
int emulate(uint8_t *buffer, uint32_t length);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* @file wifi_configuration.h
|
||||
* @brief Fill in your wifi configuration information here.
|
||||
* @version 0.1
|
||||
* @date 2020-01-22
|
||||
*
|
||||
* @copyright Copyright (c) 2020
|
||||
*
|
||||
*/
|
||||
#ifndef __WIFI_CONFIGURATION__
|
||||
#define __WIFI_CONFIGURATION__
|
||||
|
||||
#define EXAMPLE_WIFI_SSID "DAP"
|
||||
#define EXAMPLE_WIFI_PASS "12345678"
|
||||
|
||||
#define PORT 22350
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue