newtx/usb/usb_dev.cpp

777 lines
22 KiB
C++
Raw Normal View History

2023-12-01 09:17:09 +00:00
#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)
{
2023-12-01 10:03:10 +00:00
ret = write(gadget_.usb_device, &ffs_strs_, ffs_strs_.header.length);
if(ret != ffs_strs_.header.length)
2023-12-01 09:17:09 +00:00
{
ret = errno;
utils::to_log(LOG_LEVEL_FATAL, "config device with ffs_strings failed: %d - %s\n", errno, strerror(errno));
}
2023-12-01 10:03:10 +00:00
else
{
ret = 0;
}
}
else
{
ret = 0;
2023-12-01 09:17:09 +00:00
}
}
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;
2023-12-09 10:21:05 +00:00
{
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;
2023-12-09 10:21:05 +00:00
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));
}
}
2023-12-01 09:17:09 +00:00
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;
2023-12-01 09:17:09 +00:00
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));
}
}
2023-12-01 09:17:09 +00:00
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;
2023-12-01 09:17:09 +00:00
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_;
}