777 lines
22 KiB
C++
777 lines
22 KiB
C++
#include "usb_dev.h"
|
|
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <sys/ioctl.h>
|
|
#include "usbstring.h"
|
|
#include "default_cfg.h"
|
|
#include <errno.h>
|
|
#include <iostream>
|
|
#include <fstream>
|
|
|
|
|
|
#define CONFIG_VALUE 1
|
|
#define USB_MAX_PACKAGE_LENGTH_FILE "/opt/usbpkgconfig"
|
|
|
|
static struct usb_gadget_strings strings = {
|
|
.language = 0x0409, /* en-us */
|
|
.strings = 0,
|
|
};
|
|
|
|
typedef struct camtp_device_status_ {
|
|
uint16_t wLength;
|
|
uint16_t wCode;
|
|
}camtp_device_status;
|
|
|
|
static const int cacheSize = SIZE_KB(64);
|
|
|
|
usb_device::usb_device(const char* dwc3, const char* udc, const char* pwd)
|
|
: dwc3_(dwc3), udc_(udc), pwd_(pwd)
|
|
{
|
|
memset(&gadget_, 0, sizeof(gadget_));
|
|
gadget_.usb_device = -1;
|
|
for(int i = 0; i < _countof(gadget_.ep_handles); ++i)
|
|
gadget_.ep_handles[i] = -1;
|
|
|
|
memset( &ffs_strs_, 0, sizeof(ffs_strings));
|
|
ffs_strs_.header.magic = htole32(FUNCTIONFS_STRINGS_MAGIC);
|
|
ffs_strs_.header.length = htole32(sizeof(struct usb_functionfs_strings_head) + sizeof(uint16_t) + strlen(USB_INTERFACE) + 1);
|
|
ffs_strs_.header.str_count = htole32(1);
|
|
ffs_strs_.header.lang_count = htole32(1);
|
|
ffs_strs_.code = htole16(0x0409); // en-us
|
|
strcpy(ffs_strs_.string_data, USB_INTERFACE);
|
|
}
|
|
|
|
usb_device::~usb_device()
|
|
{
|
|
close_device();
|
|
deinit_usb_camtp_gadget();
|
|
}
|
|
|
|
std::string usb_device::endpoint_index_str(int epind)
|
|
{
|
|
RETURN_ENUM_STR(epind, EP_IND_BULK_IN);
|
|
RETURN_ENUM_STR(epind, EP_IND_BULK_OUT);
|
|
RETURN_ENUM_STR(epind, EP_IND_INT_IN);
|
|
|
|
return std::to_string(epind);
|
|
}
|
|
|
|
void usb_device::fill_if_descriptor(bool ffs_mode, usb_gadget * usbctx, struct usb_interface_descriptor * desc)
|
|
{
|
|
memset(desc,0,sizeof(struct usb_interface_descriptor));
|
|
|
|
desc->bLength = sizeof(struct usb_interface_descriptor);
|
|
desc->bDescriptorType = USB_DT_INTERFACE; //!< nick
|
|
desc->bInterfaceNumber = 0;
|
|
desc->iInterface = 1;
|
|
desc->bAlternateSetting = 0;
|
|
desc->bNumEndpoints = _countof(usbctx->ep_path);
|
|
|
|
desc->bInterfaceClass = USB_DEV_CLASS;
|
|
desc->bInterfaceSubClass = USB_DEV_SUBCLASS;
|
|
desc->bInterfaceProtocol = USB_DEV_PROTOCOL;
|
|
if( ffs_mode )
|
|
{
|
|
desc->iInterface = STRINGID_MANUFACTURER;
|
|
}
|
|
else
|
|
{
|
|
desc->iInterface = STRINGID_INTERFACE;
|
|
}
|
|
}
|
|
void usb_device::fill_ep_descriptor(unsigned short max_packet, usb_gadget * usbctx,struct usb_endpoint_descriptor_no_audio * desc,int index,unsigned int flags)
|
|
{
|
|
memset(desc,0,sizeof(struct usb_endpoint_descriptor_no_audio));
|
|
|
|
desc->bLength = USB_DT_ENDPOINT_SIZE;
|
|
desc->bDescriptorType = USB_DT_ENDPOINT;
|
|
|
|
if(flags & EP_OUT_DIR)
|
|
desc->bEndpointAddress = USB_DIR_OUT | (index);
|
|
else
|
|
desc->bEndpointAddress = USB_DIR_IN | (index);
|
|
|
|
if(flags & EP_BULK_MODE)
|
|
{
|
|
desc->bmAttributes = USB_ENDPOINT_XFER_BULK;
|
|
desc->wMaxPacketSize = max_packet;
|
|
//printf("desc->wMaxPacketSize = %d \n",desc->wMaxPacketSize);
|
|
}
|
|
else
|
|
{
|
|
desc->bmAttributes = USB_ENDPOINT_XFER_INT;
|
|
desc->wMaxPacketSize = 64; // HS size 64
|
|
desc->bInterval = 6;
|
|
}
|
|
|
|
#if defined(CONFIG_USB_SS_SUPPORT)
|
|
if(flags & EP_SS_MODE)
|
|
{
|
|
ep_cfg_descriptor * ss_descriptor;
|
|
|
|
ss_descriptor = (ep_cfg_descriptor *)desc;
|
|
|
|
ss_descriptor->ep_desc_comp.bLength = sizeof(struct usb_ss_ep_comp_descriptor);
|
|
ss_descriptor->ep_desc_comp.bDescriptorType = USB_DT_SS_ENDPOINT_COMP;
|
|
if(flags & EP_BULK_MODE){
|
|
ss_descriptor->ep_desc_comp.bMaxBurst = 15;
|
|
ss_descriptor->ep_desc_comp.wBytesPerInterval = 0x00;
|
|
}else{
|
|
ss_descriptor->ep_desc_comp.bMaxBurst = 0;
|
|
ss_descriptor->ep_desc_comp.wBytesPerInterval = 64;//0x1c
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
int usb_device::add_usb_string(usb_gadget * usbctx, int id, char * string)
|
|
{
|
|
int i;
|
|
|
|
i = 0;
|
|
|
|
while( i < MAX_USB_STRING )
|
|
{
|
|
if( !usbctx->stringtab[i].id )
|
|
{
|
|
usbctx->stringtab[i].id = id;
|
|
if(string)
|
|
{
|
|
usbctx->stringtab[i].str = (char*)malloc(strlen(string) + 1);
|
|
if(usbctx->stringtab[i].str)
|
|
{
|
|
memset(usbctx->stringtab[i].str,0,strlen(string) + 1);
|
|
strcpy(usbctx->stringtab[i].str,string);
|
|
return i;
|
|
}
|
|
else
|
|
{
|
|
usbctx->stringtab[i].id = 0;
|
|
return -2;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
i++;
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
void usb_device::fill_config_descriptor(usb_gadget * usbctx,struct usb_config_descriptor * desc,int total_size, int hs)
|
|
{
|
|
memset(desc,0,sizeof(struct usb_config_descriptor));
|
|
|
|
desc->bLength = sizeof(struct usb_config_descriptor);
|
|
desc->bDescriptorType = USB_DT_CONFIG;
|
|
desc->wTotalLength = desc->bLength + total_size;
|
|
desc->bNumInterfaces = 1;
|
|
desc->bConfigurationValue = CONFIG_VALUE;
|
|
if(hs)
|
|
desc->iConfiguration = STRINGID_CONFIG_HS;
|
|
else
|
|
desc->iConfiguration = STRINGID_CONFIG_LS;
|
|
desc->bmAttributes = USB_CONFIG_ATT_ONE;
|
|
desc->bMaxPower = 1;
|
|
}
|
|
void usb_device::fill_dev_descriptor(usb_gadget * usbctx,struct usb_device_descriptor * desc)
|
|
{
|
|
memset(desc,0,sizeof(struct usb_device_descriptor));
|
|
|
|
desc->bLength = USB_DT_DEVICE_SIZE;
|
|
desc->bDescriptorType = USB_DT_DEVICE;
|
|
desc->bDeviceClass = USB_DEV_CLASS;
|
|
desc->bDeviceSubClass = USB_DEV_SUBCLASS;
|
|
desc->bDeviceProtocol = USB_DEV_PROTOCOL;
|
|
desc->idVendor = USB_DEV_VENDOR_ID;
|
|
desc->idProduct = USB_DEV_PRODUCT_ID;
|
|
desc->bcdDevice = USB_DEV_VERSION; // Version
|
|
// Strings
|
|
desc->iManufacturer = STRINGID_MANUFACTURER;
|
|
desc->iProduct = STRINGID_PRODUCT;
|
|
desc->iSerialNumber = STRINGID_SERIAL;
|
|
desc->bNumConfigurations= 1; // Only one configuration
|
|
|
|
return;
|
|
}
|
|
void usb_device::init_usb_camtp_gadget(bool ffs_mode)
|
|
{
|
|
usb_gadget *usbctx = &gadget_; //(usb_gadget *)malloc(sizeof(usb_gadget));
|
|
int cfg_size;
|
|
|
|
if(usbctx)
|
|
{
|
|
std::ifstream fs(USB_MAX_PACKAGE_LENGTH_FILE);
|
|
int maxpackagesize = 0;
|
|
fs >> maxpackagesize;
|
|
if(maxpackagesize <= 0)
|
|
maxpackagesize = 512;
|
|
|
|
max_packet_ = maxpackagesize;
|
|
memset(usbctx, 0, sizeof(usb_gadget));
|
|
usbctx->usb_device = -1;
|
|
for(int i = 0; i < _countof(usbctx->ep_handles); ++i)
|
|
usbctx->ep_handles[i] = -1;
|
|
|
|
add_usb_string(usbctx, STRINGID_MANUFACTURER, MANUFACTURER);
|
|
add_usb_string(usbctx, STRINGID_PRODUCT, PRODUCT);
|
|
add_usb_string(usbctx, STRINGID_SERIAL, SERIALNUMBER);
|
|
add_usb_string(usbctx, STRINGID_CONFIG_HS, (char*)"High speed configuration");
|
|
add_usb_string(usbctx, STRINGID_CONFIG_LS, (char*)"Low speed configuration");
|
|
add_usb_string(usbctx, STRINGID_INTERFACE, USB_INTERFACE);
|
|
add_usb_string(usbctx, STRINGID_MAX, NULL);
|
|
|
|
strings.strings = usbctx->stringtab;
|
|
|
|
for(int i = 0; i < _countof(usbctx->ep_config); ++i)
|
|
{
|
|
usbctx->ep_config[i] = (ep_cfg*)malloc(sizeof(ep_cfg));
|
|
if(!usbctx->ep_config[i])
|
|
goto init_error;
|
|
|
|
memset(usbctx->ep_config[i], 0, sizeof(ep_cfg));
|
|
}
|
|
|
|
usbctx->ep_path[EP_IND_BULK_IN] = &ep_path_[EP_IND_BULK_IN][0];
|
|
usbctx->ep_path[EP_IND_BULK_OUT] = &ep_path_[EP_IND_BULK_OUT][0];
|
|
usbctx->ep_path[EP_IND_INT_IN] = &ep_path_[EP_IND_INT_IN][0];
|
|
|
|
cfg_size = sizeof(struct usb_interface_descriptor) + (sizeof(struct usb_endpoint_descriptor_no_audio) * _countof(usbctx->ep_config));
|
|
|
|
if( ffs_mode )
|
|
{
|
|
// FunctionFS mode
|
|
usbctx->usb_ffs_config = (usb_ffs_cfg *)malloc(sizeof(usb_ffs_cfg));
|
|
if(!usbctx->usb_ffs_config)
|
|
goto init_error;
|
|
|
|
memset(usbctx->usb_ffs_config, 0, sizeof(usb_ffs_cfg));
|
|
|
|
#ifdef OLD_FUNCTIONFS_DESCRIPTORS // Kernel < v3.15
|
|
usbctx->usb_ffs_config->magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC);
|
|
#else
|
|
usbctx->usb_ffs_config->magic = htole32(FUNCTIONFS_DESCRIPTORS_MAGIC_V2);
|
|
usbctx->usb_ffs_config->flags = htole32(0);
|
|
usbctx->usb_ffs_config->flags |= htole32(FUNCTIONFS_ALL_CTRL_RECIP);
|
|
|
|
#ifdef CONFIG_USB_FS_SUPPORT
|
|
usbctx->usb_ffs_config->flags |= htole32(FUNCTIONFS_HAS_FS_DESC);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_HS_SUPPORT
|
|
usbctx->usb_ffs_config->flags |= htole32(FUNCTIONFS_HAS_HS_DESC);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_SS_SUPPORT
|
|
usbctx->usb_ffs_config->flags |= htole32(FUNCTIONFS_HAS_SS_DESC);
|
|
#endif
|
|
|
|
#endif
|
|
usbctx->usb_ffs_config->length = htole32(sizeof(usb_ffs_cfg));
|
|
|
|
#ifdef CONFIG_USB_FS_SUPPORT
|
|
usbctx->usb_ffs_config->fs_count = htole32(1 + _countof(usbctx->ep_config));
|
|
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_ffs_config->ep_desc_fs.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_fs.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_fs.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_fs.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_HS_SUPPORT
|
|
usbctx->usb_ffs_config->hs_count = htole32(1 + _countof(usbctx->ep_config));
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_ffs_config->ep_desc_hs.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_hs.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR | EP_HS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_hs.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR | EP_HS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_hs.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR | EP_HS_MODE);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_SS_SUPPORT
|
|
usbctx->usb_ffs_config->ss_count = htole32(1 + (_countof(usbctx->ep_config) * 2));
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_ffs_config->ep_desc_ss.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_ss.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR | EP_SS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_ss.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR | EP_SS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_ffs_config->ep_desc_ss.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR | EP_SS_MODE);
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
usbctx->usb_config = (usb_cfg *)malloc(sizeof(usb_cfg));
|
|
if(!usbctx->usb_config)
|
|
goto init_error;
|
|
|
|
memset(usbctx->usb_config,0,sizeof(usb_cfg));
|
|
|
|
usbctx->usb_config->head = 0x00000000;
|
|
|
|
#ifdef CONFIG_USB_FS_SUPPORT
|
|
fill_config_descriptor(usbctx, &usbctx->usb_config->cfg_fs, cfg_size, 0);
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_config->ep_desc_fs.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_fs.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_fs.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_fs.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_HS_SUPPORT
|
|
fill_config_descriptor(usbctx, &usbctx->usb_config->cfg_hs, cfg_size, 1);
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_config->ep_desc_hs.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_hs.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR | EP_HS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_hs.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR | EP_HS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_hs.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR | EP_HS_MODE);
|
|
#endif
|
|
|
|
#ifdef CONFIG_USB_SS_SUPPORT
|
|
fill_config_descriptor(usbctx, &usbctx->usb_config->cfg_ss, cfg_size, 1);
|
|
fill_if_descriptor(ffs_mode, usbctx, &usbctx->usb_config->ep_desc_ss.if_desc);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_ss.ep_desc_in, EP_IND_BULK_IN + 1, EP_BULK_MODE | EP_IN_DIR | EP_SS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_ss.ep_desc_out, EP_IND_BULK_OUT + 1, EP_BULK_MODE | EP_OUT_DIR | EP_SS_MODE);
|
|
fill_ep_descriptor(maxpackagesize, usbctx, &usbctx->usb_config->ep_desc_ss.ep_desc_int_in, EP_IND_INT_IN + 1, EP_INT_MODE | EP_IN_DIR | EP_SS_MODE);
|
|
#endif
|
|
|
|
fill_dev_descriptor(usbctx, &usbctx->usb_config->dev_desc);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
init_error:
|
|
deinit_usb_camtp_gadget();
|
|
}
|
|
void usb_device::deinit_usb_camtp_gadget()
|
|
{
|
|
usb_gadget * usbctx = &gadget_;
|
|
|
|
if( usbctx )
|
|
{
|
|
if(usbctx->usb_config)
|
|
{
|
|
free(usbctx->usb_config);
|
|
usbctx->usb_config = 0;
|
|
}
|
|
|
|
if(usbctx->usb_ffs_config)
|
|
{
|
|
free(usbctx->usb_ffs_config);
|
|
usbctx->usb_ffs_config = 0;
|
|
}
|
|
|
|
for(int i = 0; i < _countof(usbctx->ep_config); ++i)
|
|
{
|
|
if( usbctx->ep_config[i] )
|
|
free( usbctx->ep_config[i] );
|
|
usbctx->ep_config[i] = nullptr;
|
|
}
|
|
|
|
for(int i = 0; i < _countof(usbctx->stringtab); ++i)
|
|
{
|
|
if( usbctx->stringtab[i].str )
|
|
free ( usbctx->stringtab[i].str );
|
|
usbctx->stringtab[i].str = nullptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
int usb_device::config_device(bool ffs_mode)
|
|
{
|
|
void *data = ffs_mode ? (void*)gadget_.usb_ffs_config : (void*)gadget_.usb_config;
|
|
int size = ffs_mode ? sizeof(*gadget_.usb_ffs_config) : sizeof(*gadget_.usb_config),
|
|
ret = write(gadget_.usb_device, data, size);
|
|
|
|
if(ret == size)
|
|
{
|
|
if(ffs_mode)
|
|
{
|
|
ret = write(gadget_.usb_device, &ffs_strs_, ffs_strs_.header.length);
|
|
if(ret != ffs_strs_.header.length)
|
|
{
|
|
ret = errno;
|
|
utils::to_log(LOG_LEVEL_FATAL, "config device with ffs_strings failed: %d - %s\n", errno, strerror(errno));
|
|
}
|
|
else
|
|
{
|
|
ret = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = errno;
|
|
utils::to_log(LOG_LEVEL_FATAL, "config device with '%s' failed: %d - %s\n", ffs_mode ? "ffs_config" : "usb_config", errno, strerror(errno));
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::config_endpoint(int ep_ind)
|
|
{
|
|
int ret = 0;
|
|
|
|
void * descriptor_ptr;
|
|
int descriptor_size;
|
|
int index = ep_ind;
|
|
usb_gadget* ctx = &gadget_;
|
|
|
|
ctx->ep_config[index]->head = 1;
|
|
descriptor_size = 0;
|
|
|
|
if( ctx->usb_ffs_config )
|
|
{
|
|
#if defined(CONFIG_USB_SS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_ffs_config->ep_desc_ss;
|
|
descriptor_size = sizeof(ep_cfg_descriptor);
|
|
#elif defined(CONFIG_USB_HS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_ffs_config->ep_desc_hs;
|
|
descriptor_size = sizeof(struct usb_endpoint_descriptor_no_audio);
|
|
#elif defined(CONFIG_USB_FS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_ffs_config->ep_desc_fs;
|
|
descriptor_size = sizeof(struct usb_endpoint_descriptor_no_audio);
|
|
#else
|
|
|
|
#error Configuration Error ! At least one USB mode support must be enabled ! (CONFIG_USB_FS_SUPPORT/CONFIG_USB_HS_SUPPORT/CONFIG_USB_SS_SUPPORT)
|
|
|
|
#endif
|
|
}
|
|
else
|
|
{
|
|
#if defined(CONFIG_USB_SS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_config->ep_desc_ss;
|
|
descriptor_size = sizeof(ep_cfg_descriptor);
|
|
#elif defined(CONFIG_USB_HS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_config->ep_desc_hs;
|
|
descriptor_size = sizeof(struct usb_endpoint_descriptor_no_audio);
|
|
#elif defined(CONFIG_USB_FS_SUPPORT)
|
|
descriptor_ptr = (void *)&ctx->usb_config->ep_desc_fs;
|
|
descriptor_size = sizeof(struct usb_endpoint_descriptor_no_audio);
|
|
#else
|
|
|
|
#error Configuration Error ! At least one USB mode support must be enabled ! (CONFIG_USB_FS_SUPPORT/CONFIG_USB_HS_SUPPORT/CONFIG_USB_SS_SUPPORT)
|
|
|
|
#endif
|
|
}
|
|
|
|
#if defined(CONFIG_USB_SS_SUPPORT)
|
|
switch(index)
|
|
{
|
|
case EP_DESCRIPTOR_IN:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_in,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_in,descriptor_size);
|
|
break;
|
|
case EP_DESCRIPTOR_OUT:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_out,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_out,descriptor_size);
|
|
break;
|
|
case EP_DESCRIPTOR_INT_IN:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_int_in,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((SSEndPointsDesc*)descriptor_ptr)->ep_desc_int_in,descriptor_size);
|
|
break;
|
|
}
|
|
#else
|
|
switch(index)
|
|
{
|
|
case EP_DESCRIPTOR_IN:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((EndPointsDesc*)descriptor_ptr)->ep_desc_in,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((EndPointsDesc*)descriptor_ptr)->ep_desc_in,descriptor_size);
|
|
break;
|
|
case EP_DESCRIPTOR_OUT:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((EndPointsDesc*)descriptor_ptr)->ep_desc_out,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((EndPointsDesc*)descriptor_ptr)->ep_desc_out,descriptor_size);
|
|
break;
|
|
case EP_DESCRIPTOR_INT_IN:
|
|
memcpy(&ctx->ep_config[index]->ep_desc[0], &((EndPointsDesc*)descriptor_ptr)->ep_desc_int_in,descriptor_size);
|
|
memcpy(&ctx->ep_config[index]->ep_desc[1], &((EndPointsDesc*)descriptor_ptr)->ep_desc_int_in,descriptor_size);
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
if(ffs_mode_)
|
|
{
|
|
|
|
}
|
|
else
|
|
{
|
|
ret = write(ctx->ep_handles[index], ctx->ep_config[index], sizeof(ep_cfg));
|
|
|
|
if (ret != sizeof(ep_cfg))
|
|
{
|
|
ret = errno;
|
|
utils::to_log(LOG_LEVEL_FATAL, "config_endpoint '%s' failed: %d - %s", usb_device::endpoint_index_str(index).c_str(), errno, strerror(errno));
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int usb_device::add_endpoint(const char* path, bool bulk/*true - bulk, false - int*/, bool in)
|
|
{
|
|
int ret = 0, ind = -1;
|
|
if(bulk)
|
|
{
|
|
if(in)
|
|
ind = EP_IND_BULK_IN;
|
|
else
|
|
ind = EP_IND_BULK_OUT;
|
|
}
|
|
else
|
|
{
|
|
if(in)
|
|
ind = EP_IND_INT_IN;
|
|
}
|
|
|
|
if(ind == -1)
|
|
ret = EINVAL;
|
|
else
|
|
ep_path_[ind] = path ? path : "";
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::open_device(const char* dev, bool ffs_mode, int* fd)
|
|
{
|
|
int ret = close_device();
|
|
|
|
if(fd)
|
|
*fd = -1;
|
|
|
|
if(ret == 0)
|
|
{
|
|
init_usb_camtp_gadget(ffs_mode);
|
|
gadget_.usb_device = open(dev, O_RDWR | O_SYNC);
|
|
if(gadget_.usb_device == -1)
|
|
{
|
|
ret = errno;
|
|
utils::to_log(LOG_LEVEL_FATAL, "Open usb device(%s) failed: %d - %s\n", dev, ret, strerror(ret));
|
|
}
|
|
else
|
|
{
|
|
ret = config_device(ffs_mode);
|
|
if(ret)
|
|
{
|
|
close_device();
|
|
}
|
|
else
|
|
{
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Open usb device(%s) success.\n", dev);
|
|
ffs_mode_ = ffs_mode;
|
|
|
|
// get_system_output(R"(echo linaro | sudo -S sh -c "chmod 777 /dev/ffs-camtp -R")");
|
|
std::string cmd(dev);
|
|
size_t pos = cmd.rfind('/');
|
|
|
|
if(pos != std::string::npos)
|
|
cmd.erase(pos);
|
|
cmd += " -R\"";
|
|
cmd.insert(0, "echo " + pwd_ + " | sudo -S sh -c \"chmod 777 ");
|
|
utils::get_command_result(cmd.c_str());
|
|
}
|
|
if(fd)
|
|
*fd = gadget_.usb_device;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::open_endpoint(int ep_ind, int* fd)
|
|
{
|
|
int ret = ENOTCONN;
|
|
|
|
if(fd)
|
|
*fd = -1;
|
|
|
|
if(gadget_.usb_device >= 0)
|
|
{
|
|
if(ep_ind >= 0 && ep_ind < _countof(gadget_.ep_handles))
|
|
{
|
|
if(gadget_.ep_handles[ep_ind] >= 0)
|
|
{
|
|
ret = EALREADY;
|
|
}
|
|
else
|
|
{
|
|
gadget_.ep_handles[ep_ind] = open(gadget_.ep_path[ep_ind], O_RDWR);
|
|
if(gadget_.ep_handles[ep_ind] == -1)
|
|
{
|
|
utils::to_log(LOG_LEVEL_FATAL, "open endpoint(%s - %s) failed: %d - %s\n", usb_device::endpoint_index_str(ep_ind).c_str(), gadget_.ep_path[ep_ind], errno, strerror(errno));
|
|
ret = errno;
|
|
}
|
|
else
|
|
{
|
|
ret = config_endpoint(ep_ind);
|
|
if(ret)
|
|
{
|
|
close(gadget_.ep_handles[ep_ind]);
|
|
gadget_.ep_handles[ep_ind] = -1;
|
|
}
|
|
else
|
|
{
|
|
utils::to_log(LOG_LEVEL_DEBUG, "open endpoint(%s - %s) ok.\n", usb_device::endpoint_index_str(ep_ind).c_str(), gadget_.ep_path[ep_ind]);
|
|
}
|
|
}
|
|
}
|
|
if(fd)
|
|
*fd = gadget_.ep_handles[ep_ind];
|
|
}
|
|
else
|
|
{
|
|
ret = EINVAL;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::close_endpoint(int ep_ind)
|
|
{
|
|
int ret = 0;
|
|
|
|
if(ep_ind == -1)
|
|
{
|
|
for(int i = 0; i < _countof(gadget_.ep_handles); ++i)
|
|
{
|
|
if(gadget_.ep_handles[i] != -1)
|
|
{
|
|
ret = close(gadget_.ep_handles[i]);
|
|
if(ret)
|
|
{
|
|
utils::to_log(LOG_LEVEL_FATAL, "close endpoint(%s) failed: %d(%s)\n", usb_device::endpoint_index_str(i).c_str(), errno, strerror(errno));
|
|
break;
|
|
}
|
|
gadget_.ep_handles[i] = -1;
|
|
}
|
|
}
|
|
utils::to_log(LOG_LEVEL_DEBUG, "close all endpoints = %d\n", ret);
|
|
}
|
|
else if(ep_ind >= 0 && ep_ind < _countof(gadget_.ep_handles))
|
|
{
|
|
if(gadget_.ep_handles[ep_ind] != -1)
|
|
{
|
|
ret = close(gadget_.ep_handles[ep_ind]);
|
|
if(ret)
|
|
utils::to_log(LOG_LEVEL_FATAL, "close endpoint(%s) failed: %d(%s)\n", usb_device::endpoint_index_str(ep_ind).c_str(), errno, strerror(errno));
|
|
else
|
|
{
|
|
gadget_.ep_handles[ep_ind] = -1;
|
|
utils::to_log(LOG_LEVEL_DEBUG, "close endpoint(%s) ok.\n", usb_device::endpoint_index_str(ep_ind).c_str());
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ret = EINVAL;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::close_device(void)
|
|
{
|
|
int ret = pull_down();
|
|
|
|
if(ret == 0)
|
|
{
|
|
ret = close_endpoint(-1);
|
|
if(ret == 0)
|
|
{
|
|
deinit_usb_camtp_gadget();
|
|
if(gadget_.usb_device >= 0)
|
|
{
|
|
ret = close(gadget_.usb_device);
|
|
if(ret == 0)
|
|
gadget_.usb_device = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
int usb_device::pull_up(std::string* msg)
|
|
{
|
|
if(on_)
|
|
return 0;
|
|
|
|
{
|
|
int dst = open(udc_.c_str(), O_RDWR);
|
|
if(dst == -1)
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Try write '%s' to '%s' failed(open): %s\n", dwc3_.c_str(), udc_.c_str(), strerror(errno));
|
|
else
|
|
{
|
|
int l = write(dst, dwc3_.c_str(), dwc3_.length()),
|
|
err = errno;
|
|
close(dst);
|
|
if(l == dwc3_.length())
|
|
{
|
|
utils::to_log(LOG_LEVEL_DEBUG, "pull up device by write '%s' to '%s' directly success.\n", dwc3_.c_str(), udc_.c_str());
|
|
on_ = true;
|
|
return 0;
|
|
}
|
|
else
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Try write '%s' to '%s' failed(write): %s\n", dwc3_.c_str(), udc_.c_str(), strerror(errno));
|
|
}
|
|
}
|
|
|
|
std::string cmd("echo " + pwd_ + " | sudo -S sh -c \"echo " + dwc3_ + " > " + udc_ + "\"");
|
|
int err = 0;
|
|
std::string info(utils::get_command_result(cmd.c_str(), -1, &err));
|
|
|
|
if(err == 0)
|
|
on_ = true;
|
|
|
|
if(msg)
|
|
*msg = std::move(info);
|
|
|
|
return err;
|
|
}
|
|
int usb_device::pull_down(void)
|
|
{
|
|
if(!on_)
|
|
return 0;
|
|
|
|
{
|
|
int dst = open(udc_.c_str(), O_RDWR);
|
|
if(dst == -1)
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Try write empty to '%s' failed(open): %s\n", udc_.c_str(), strerror(errno));
|
|
else
|
|
{
|
|
int e = 0;
|
|
int l = write(dst, &e, 1),
|
|
err = errno;
|
|
close(dst);
|
|
if(l == 1)
|
|
{
|
|
utils::to_log(LOG_LEVEL_DEBUG, "pull down device by write '' to '%s' directly success.\n", udc_.c_str());
|
|
on_ = false;
|
|
return 0;
|
|
}
|
|
else
|
|
utils::to_log(LOG_LEVEL_DEBUG, "Try write '' to '%s' failed(write): %s\n", udc_.c_str(), strerror(errno));
|
|
}
|
|
}
|
|
|
|
std::string cmd("echo " + pwd_ + " | sudo -S sh -c \"echo " + "''" + " > " + udc_ + "\"");
|
|
int err = 0;
|
|
|
|
utils::get_command_result(cmd.c_str(), -1, &err);
|
|
if(err == 0)
|
|
on_ = false;
|
|
|
|
return err;
|
|
}
|
|
|
|
int usb_device::get_device_fd(void)
|
|
{
|
|
return gadget_.usb_device;
|
|
}
|
|
int usb_device::get_endpoint_fd(int ep_ind)
|
|
{
|
|
if(ep_ind >= 0 && ep_ind < _countof(gadget_.ep_handles))
|
|
return gadget_.ep_handles[ep_ind];
|
|
else
|
|
return -1;
|
|
}
|
|
size_t usb_device::get_max_packet(void)
|
|
{
|
|
return max_packet_;
|
|
}
|