/* * (C) Copyright 2017 Fuzhou Rockchip Electronics Co., Ltd * Seth Liu 2017.03.01 * * SPDX-License-Identifier: GPL-2.0+ */ #include "RKScan.h" #define BUSID(id) ((id & 0x0000FF00) >> 8) int CRKScan::GetDEVICE_COUNTS() { return m_list.size(); } UINT CRKScan::GetMSC_TIMEOUT() { return m_waitMscSecond; } UINT CRKScan::GetRKUSB_TIMEOUT() { return m_waitRKusbSecond; } void CRKScan::SetMSC_TIMEOUT(UINT value) { m_waitMscSecond = value; } void CRKScan::SetRKUSB_TIMEOUT(UINT value) { m_waitRKusbSecond = value; } CRKScan::CRKScan(UINT uiMscTimeout, UINT uiRKusbTimeout) { DEVICE_COUNTS.setContainer(this); DEVICE_COUNTS.getter(&CRKScan::GetDEVICE_COUNTS); MSC_TIMEOUT.setContainer(this); MSC_TIMEOUT.getter(&CRKScan::GetMSC_TIMEOUT); MSC_TIMEOUT.setter(&CRKScan::SetMSC_TIMEOUT); RKUSB_TIMEOUT.setContainer(this); RKUSB_TIMEOUT.getter(&CRKScan::GetRKUSB_TIMEOUT); RKUSB_TIMEOUT.setter(&CRKScan::SetRKUSB_TIMEOUT); m_waitMscSecond = uiMscTimeout; m_waitRKusbSecond = uiRKusbTimeout; m_log = NULL; m_list.clear(); m_deviceConfigSet.clear(); m_deviceMscConfigSet.clear(); } bool CRKScan::FindRockusbVidPid(ENUM_RKDEVICE_TYPE type, USHORT &usVid, USHORT &usPid) { UINT i; bool bRet = false; for (i = 0; i < m_deviceConfigSet.size(); i++) { if (m_deviceConfigSet[i].emDeviceType == type) { usVid = m_deviceConfigSet[i].usVid; usPid = m_deviceConfigSet[i].usPid; bRet = true; break; } } return bRet; } void CRKScan::AddRockusbVidPid(USHORT newVid, USHORT newPid, USHORT oldVid, USHORT oldPid) { if ((newVid == 0) || (newPid == 0) || (oldVid == 0) || (oldPid == 0)) { return; } STRUCT_DEVICE_CONFIG config; unsigned int i; for (i = 0; i < m_deviceConfigSet.size(); i++) { if ((m_deviceConfigSet[i].usVid == oldVid) && (m_deviceConfigSet[i].usPid == oldPid)) { config.usVid = newVid; config.usPid = newPid; config.emDeviceType = m_deviceConfigSet[i].emDeviceType; break; } } if (i < m_deviceConfigSet.size()) m_deviceConfigSet.push_back(config); } void CRKScan::SetVidPid(USHORT mscVid, USHORT mscPid) { STRUCT_DEVICE_CONFIG config; m_deviceConfigSet.clear(); config.emDeviceType = RK27_DEVICE; config.usPid = 0x3201; config.usVid = 0x071B; m_deviceConfigSet.push_back(config); config.emDeviceType = RK28_DEVICE; config.usPid = 0x3228; config.usVid = 0x071B; m_deviceConfigSet.push_back(config); config.emDeviceType = RKNANO_DEVICE; config.usPid = 0x3226; config.usVid = 0x071B; m_deviceConfigSet.push_back(config); config.emDeviceType = RKCROWN_DEVICE; config.usPid = 0x261A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK281X_DEVICE; config.usPid = 0x281A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RKCAYMAN_DEVICE; config.usPid = 0x273A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK29_DEVICE; config.usPid = 0x290A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RKPANDA_DEVICE; config.usPid = 0x282B; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RKSMART_DEVICE; config.usPid = 0x262C; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK292X_DEVICE; config.usPid = 0x292A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK30_DEVICE; config.usPid = 0x300A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK30B_DEVICE; config.usPid = 0x300B; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK31_DEVICE; config.usPid = 0x310B; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); config.emDeviceType = RK32_DEVICE; config.usPid = 0x320A; config.usVid = 0x2207; m_deviceConfigSet.push_back(config); m_deviceMscConfigSet.clear(); config.emDeviceType = RKNONE_DEVICE; config.usPid = 0x3203; config.usVid = 0x071B; m_deviceMscConfigSet.push_back(config); config.emDeviceType = RKNONE_DEVICE; config.usPid = 0x3205; config.usVid = 0x071B; m_deviceMscConfigSet.push_back(config); config.emDeviceType = RKNONE_DEVICE; config.usPid = 0x2910; config.usVid = 0x0BB4; m_deviceMscConfigSet.push_back(config); config.emDeviceType = RKNONE_DEVICE; config.usPid = 0x0000; config.usVid = 0x2207; m_deviceMscConfigSet.push_back(config); config.emDeviceType = RKNONE_DEVICE; config.usPid = 0x0010; config.usVid = 0x2207; m_deviceMscConfigSet.push_back(config); if ((mscVid != 0) || (mscPid != 0)) { if (FindConfigSetPos(m_deviceMscConfigSet, mscVid, mscPid) == -1) { config.emDeviceType = RKNONE_DEVICE; config.usPid = mscPid; config.usVid = mscVid; m_deviceMscConfigSet.push_back(config); } } } int CRKScan::FindWaitSetPos(const RKDEVICE_CONFIG_SET &waitDeviceSet, USHORT vid, USHORT pid) { int pos=-1; UINT i; for ( i = 0; i < waitDeviceSet.size(); i++ ) { if ( (vid == waitDeviceSet[i].usVid) && (pid == waitDeviceSet[i].usPid) ) { pos = i; break; } } return pos; } int CRKScan::FindConfigSetPos(RKDEVICE_CONFIG_SET &devConfigSet, USHORT vid, USHORT pid) { int pos = -1; UINT i; for ( i = 0; i < devConfigSet.size(); i++ ) { if ( (vid == devConfigSet[i].usVid) && (pid == devConfigSet[i].usPid) ) { pos = i; break; } } return pos; } void CRKScan::EnumerateUsbDevice(RKDEVICE_DESC_SET &list, UINT &uiTotalMatchDevices) { STRUCT_RKDEVICE_DESC desc; struct libusb_device_descriptor descriptor; int ret,i,cnt; uiTotalMatchDevices = 0; libusb_device **pDevs = NULL; libusb_device *dev; ret = libusb_get_device_list(NULL, &pDevs); if (ret < 0) { if (m_log) m_log->Record("Error:EnumerateUsbDevice-->get_device_list failed,err=%d!", ret); return; } cnt = ret; for (i = 0; i < cnt; i++) { dev = pDevs[i]; if (dev) { ret = libusb_get_device_descriptor (dev, &descriptor); if (ret < 0) { libusb_free_device_list(pDevs, 1); if (m_log) m_log->Record("Error:EnumerateUsbDevice-->get_device_descriptor failed,err=%d!", ret); return; } desc.emDeviceType = RKNONE_DEVICE; desc.emUsbType = RKUSB_NONE; desc.pUsbHandle = (void *)dev; desc.usbcdUsb = descriptor.bcdUSB; desc.usVid = descriptor.idVendor; desc.usPid = descriptor.idProduct; desc.uiLocationID = libusb_get_bus_number(dev); desc.uiLocationID <<= 8; desc.uiLocationID += libusb_get_port_number(dev); libusb_ref_device(dev); uiTotalMatchDevices++; list.push_back(desc); } } libusb_free_device_list(pDevs, 1); } void CRKScan::FreeDeviceList(RKDEVICE_DESC_SET &list) { device_list_iter iter; for (iter = list.begin(); iter != list.end(); iter++) { if ((*iter).pUsbHandle) { libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); (*iter).pUsbHandle = NULL; } } list.clear(); } bool CRKScan::IsRockusbDevice(ENUM_RKDEVICE_TYPE &type, USHORT vid, USHORT pid) { int iPos; iPos = FindConfigSetPos(m_deviceConfigSet, vid, pid); if (iPos != -1) { type = m_deviceConfigSet[iPos].emDeviceType; return true; } if (vid == 0x2207) { if ((pid >> 8) > 0) { type = RKNONE_DEVICE; return true; } } return false; } int CRKScan::Search(UINT type) { device_list_iter iter,new_iter; ENUM_RKDEVICE_TYPE devType; UINT uiTotalDevice; int iPos; FreeDeviceList(m_list); EnumerateUsbDevice( m_list, uiTotalDevice ); for ( iter = m_list.begin(); iter != m_list.end(); ) { if( (iPos = FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid)) != -1 ) { (*iter).emDeviceType = RKNONE_DEVICE; iter++; continue; } else if (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid) ) { (*iter).emDeviceType = devType; iter++; continue; } else { if ((*iter).pUsbHandle) { libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); (*iter).pUsbHandle = NULL; } iter = m_list.erase(iter); uiTotalDevice--; } } if (m_list.size() <= 0) { return 0; } if ( (type & RKUSB_MASKROM) == 0 ) { for ( iter = m_list.begin(); iter != m_list.end(); ) { if( (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) && (((*iter).usbcdUsb & 0x1) == 0) ) { if ((*iter).pUsbHandle) { libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); (*iter).pUsbHandle = NULL; } iter = m_list.erase(iter); uiTotalDevice--; } else { iter++; continue; } } } if (m_list.size() <= 0) { return 0; } if ( (type & RKUSB_LOADER) == 0 ) { for ( iter = m_list.begin(); iter != m_list.end(); ) { if( (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) && (((*iter).usbcdUsb & 0x1) == 1) ) { if ((*iter).pUsbHandle) { libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); (*iter).pUsbHandle = NULL; } iter = m_list.erase(iter); uiTotalDevice--; } else { iter++; continue; } } } if (m_list.size() <= 0) { return 0; } if ( (type & RKUSB_MSC) == 0 ) { for ( iter = m_list.begin(); iter != m_list.end(); ) { if(FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1) { if ((*iter).pUsbHandle) { libusb_unref_device((libusb_device *)((*iter).pUsbHandle)); (*iter).pUsbHandle = NULL; } iter = m_list.erase(iter); uiTotalDevice--; } else { iter++; continue; } } } if (m_list.size() <= 0) { return 0; } for ( iter = m_list.begin(); iter != m_list.end(); iter++ ) { if (FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1) { (*iter).emUsbType = RKUSB_MSC; } else { USHORT usTemp; usTemp = (*iter).usbcdUsb; usTemp= usTemp & 0x1; if ( usTemp == 0 ) (*iter).emUsbType = RKUSB_MASKROM; else (*iter).emUsbType = RKUSB_LOADER; } } return m_list.size(); } bool CRKScan::MutexWait(UINT_VECTOR &vecExistedDevice, STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid, USHORT usPid) { device_list_iter iter; int uiWaitSecond; int iFoundCount = 0; UINT iRet,i; bool bFound = false; if (usbType == RKUSB_MSC) uiWaitSecond = m_waitMscSecond; else uiWaitSecond = m_waitRKusbSecond; time_t tmInit, tmNow; time(&tmInit); device.uiLocationID = 0; while( difftime(time(&tmNow), tmInit) <= uiWaitSecond ) { iRet = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); if ( iRet == vecExistedDevice.size() + 1 ) { for (i = 0; i < vecExistedDevice.size(); i++) { for (iter = m_list.begin(); iter != m_list.end(); ) { if ((*iter).uiLocationID == vecExistedDevice[i]) { iter = m_list.erase(iter); } else iter++; } } if (m_list.size() != 1) { device.uiLocationID = 0; iFoundCount = 0; } else { iter = m_list.begin(); if (device.uiLocationID == 0) { iFoundCount++; device.uiLocationID = (*iter).uiLocationID; } else { if (device.uiLocationID == (*iter).uiLocationID) { iFoundCount++; } else { device.uiLocationID = 0; iFoundCount = 0; } } } } else { device.uiLocationID = 0; iFoundCount = 0; } if (iFoundCount >= 10) { bFound = true; break; } } if (!bFound) { return false; } bFound = Wait(device, usbType, usVid, usPid); return bFound; } bool CRKScan::MutexWaitPrepare(UINT_VECTOR &vecExistedDevice, DWORD uiOfflineDevice) { int iRet, iRet2; device_list_iter iter; time_t timeInit, timeNow; time(&timeInit); iRet = iRet2 =0; while ((time(&timeNow) - timeInit) <= 3) { iRet = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); usleep(20000); iRet2 = Search(RKUSB_MASKROM | RKUSB_LOADER | RKUSB_MSC); if (iRet2 == iRet) { break; } } if ((iRet <= 0) || (iRet2 != iRet)) { return false; } vecExistedDevice.clear(); bool bFound = false; for ( iter = m_list.begin(); iter != m_list.end(); iter++ ) { if ((*iter).uiLocationID != uiOfflineDevice) { vecExistedDevice.push_back((*iter).uiLocationID); } else bFound = true; } if (!bFound) { return false; } return true; } bool CRKScan::Wait(STRUCT_RKDEVICE_DESC &device, ENUM_RKUSB_TYPE usbType, USHORT usVid, USHORT usPid) { RKDEVICE_DESC_SET deviceList; ENUM_RKUSB_TYPE curDeviceType; ENUM_RKDEVICE_TYPE devType; device_list_iter iter; UINT totalDevice; int uiWaitSecond; int iFoundCount = 0; bool bRet = false; if (usbType == RKUSB_MSC) uiWaitSecond = m_waitMscSecond; else uiWaitSecond = m_waitRKusbSecond; time_t tmInit, tmNow; time(&tmInit); while( difftime(time(&tmNow), tmInit) <= uiWaitSecond ) { FreeDeviceList(deviceList); EnumerateUsbDevice(deviceList, totalDevice); for ( iter = deviceList.begin(); iter != deviceList.end(); iter++ ) { if ((BUSID((*iter).uiLocationID) != BUSID(device.uiLocationID)) || ((BUSID((*iter).uiLocationID) == BUSID(device.uiLocationID)) && ((*iter).uiLocationID >= device.uiLocationID))) { if ((usVid != 0) || (usPid != 0)) { if ( ((*iter).usVid != usVid) || ((*iter).usPid != usPid) ) continue; } if (IsRockusbDevice(devType, (*iter).usVid, (*iter).usPid)) { if ( ((*iter).usbcdUsb & 0x0001) == 0 ) curDeviceType = RKUSB_MASKROM; else curDeviceType = RKUSB_LOADER; } else if ( FindConfigSetPos(m_deviceMscConfigSet, (*iter).usVid, (*iter).usPid) != -1 ) { curDeviceType = RKUSB_MSC; } else curDeviceType = RKUSB_NONE; if ( curDeviceType == usbType ) { iFoundCount++; break; } } } if ( iter == deviceList.end() ) { iFoundCount = 0; } if ( iFoundCount >= 8 ) { device.usVid = (*iter).usVid; device.usPid = (*iter).usPid; device.uiLocationID = (*iter).uiLocationID; device.pUsbHandle= (*iter).pUsbHandle; device.emUsbType = usbType; device.usbcdUsb = (*iter).usbcdUsb; libusb_ref_device((libusb_device *)device.pUsbHandle); if (usbType == RKUSB_MSC) { device.emDeviceType = RKNONE_DEVICE; } else { if (IsRockusbDevice(devType, device.usVid, device.usPid)) device.emDeviceType = devType; } bRet = true; break; } usleep(50000); } FreeDeviceList(deviceList); return bRet; } int CRKScan::GetPos(UINT locationID) { device_list_iter iter; int pos = 0; bool bFound = false; for (iter = m_list.begin(); iter != m_list.end(); iter++) { if (locationID == (*iter).uiLocationID) { bFound=true; break; } pos++; } return (bFound ? pos : -1); } bool CRKScan::GetDevice(STRUCT_RKDEVICE_DESC &device, int pos) { if ( (pos < 0) || (pos >= (int)m_list.size()) ) { return false; } device_list_iter iter; for (iter = m_list.begin(); iter != m_list.end(); iter++) { if (pos == 0) { break; } pos--; } device.usVid = (*iter).usVid; device.usPid = (*iter).usPid; device.emDeviceType = (*iter).emDeviceType; device.emUsbType = (*iter).emUsbType; device.uiLocationID = (*iter).uiLocationID; device.pUsbHandle= (*iter).pUsbHandle; device.usbcdUsb = (*iter).usbcdUsb; return true; } bool CRKScan::SetLogObject(CRKLog *pLog) { if (pLog) { if (m_log) { delete m_log; } m_log = pLog; } else return false; return true; } CRKScan::~CRKScan() { FreeDeviceList(m_list); if (m_log) { delete m_log; m_log = NULL; } }