#include "usb_dev.h" #include #include #include #include #include "usbstring.h" #include "default_cfg.h" #include #include #include #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, fd = %d.\n", dev, gadget_.usb_device); 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, fd = %d.\n", usb_device::endpoint_index_str(ep_ind).c_str(), gadget_.ep_path[ep_ind], gadget_.ep_handles[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; } utils::to_log(LOG_LEVEL_DEBUG, "close endpoint(%s, fd = %d) ok.\n", usb_device::endpoint_index_str(i).c_str(), gadget_.ep_handles[i]); 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 { utils::to_log(LOG_LEVEL_DEBUG, "close endpoint(%s, fd = %d) ok.\n", usb_device::endpoint_index_str(ep_ind).c_str(), gadget_.ep_handles[ep_ind]); gadget_.ep_handles[ep_ind] = -1; } } } 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) { utils::to_log(LOG_LEVEL_DEBUG, "Close usb device(fd = %d) ok.\n", gadget_.usb_device); 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_; }