diff options
Diffstat (limited to 'Src/Network/base/DriverConfiguration.c')
-rw-r--r-- | Src/Network/base/DriverConfiguration.c | 608 |
1 files changed, 608 insertions, 0 deletions
diff --git a/Src/Network/base/DriverConfiguration.c b/Src/Network/base/DriverConfiguration.c new file mode 100644 index 0000000..7a98d25 --- /dev/null +++ b/Src/Network/base/DriverConfiguration.c @@ -0,0 +1,608 @@ +/* + * Video On Demand Samples + * + * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * You may also obtain this software under a propriety license from Microchip. + * Please contact Microchip for further information. + * + */ + +#include <dirent.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <errno.h> +#include "DriverConfiguration.h" +#include "Console.h" + +static bool WriteCharactersToFile( const char *pFileName, const char *pString ) +{ + bool success = false; + FILE *fh = fopen( pFileName, "a" ); + if( NULL != fh ) + { + int result = fputs( pString, fh ); + if( result >= 0 ) + fputc( '\n', fh ); + if( result >= 0 ) + success = true; + fclose( fh ); + } + if( success ) + ConsolePrintf( PRIO_MEDIUM, "*** configured device: '%s = %s', success:%d\n", pFileName, pString, success ); + else + ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.WriteCharactersToFile failed for file '%s', errno:'%s'"RESETCOLOR"\n", + pFileName, GetErrnoString() ); + return success; +} + +static bool WriteIntegerToFile( const char *pFileName, int intValue ) +{ + char tempBuffer[16]; + snprintf( tempBuffer, sizeof( tempBuffer ), "%d", intValue ); + return WriteCharactersToFile( pFileName, tempBuffer ); +} + +static bool ReadFromFile( const char *pFileName, char *pString, uint16_t bufferLen ) +{ + bool success = false; + if( NULL == pString || 0 == bufferLen ) + return success; + FILE *fh = fopen( pFileName, "r" ); + if( NULL != fh ) + { + success = ( NULL != fgets( pString, bufferLen, fh ) ); + fclose( fh ); + } + if( !success ) + ConsolePrintf( PRIO_ERROR, RED"DriverConfiguration.ReadFromFile failed for file '%s', errno:'%s'"RESETCOLOR"\n", + pFileName, GetErrnoString() ); + return success; +} + +static bool ExistsDevice( const char *pDeviceName ) +{ + struct stat buffer; + return ( stat( pDeviceName, &buffer ) == 0 ); +} + +static bool WaitForDevice( const char *pDeviceName ) +{ + int timeout; + bool deviceExists = false; + for( timeout = 0; timeout < 40; timeout++ ) + { + deviceExists = ExistsDevice( pDeviceName ); + if( deviceExists ) + { + break; + } + else + { + usleep( 2500 ); + } + } + if( !deviceExists ) + ConsolePrintf( PRIO_ERROR, RED"Waiting for device '%s' to appear, timed out"RESETCOLOR"\n", + pDeviceName ); + return deviceExists; +} + +static bool GetDeviceDescription( uint8_t deviceInstance, char *deviceString, uint32_t stringLen ) +{ + bool descriptionFound = false; + char descriptionPath[64]; + char descriptionValue[32]; + + if( NULL == deviceString ) + return descriptionFound; + + snprintf( descriptionPath, sizeof( descriptionPath ), + "/sys/devices/virtual/most/mostcore/devices/mdev%d/description", deviceInstance ); + + if( !ExistsDevice( descriptionPath ) ) + return descriptionFound; + + descriptionFound = ReadFromFile( descriptionPath, descriptionValue, sizeof( descriptionValue ) ); + if( descriptionFound ) + { + strncpy( deviceString, descriptionValue, stringLen ); + } + return descriptionFound; +} + +static bool ExistsDeviceWithType( uint8_t deviceInstance, const char *deviceString, uint32_t stringLen ) +{ + bool deviceFound = false; + char interfacePath[64]; + char interfaceValue[32]; + + if( NULL == deviceString ) + return deviceFound; + + snprintf( interfacePath, sizeof( interfacePath ), "/sys/devices/virtual/most/mostcore/devices/mdev%d/interface", + deviceInstance ); + + if( !ExistsDevice( interfacePath ) ) + return deviceFound; + + deviceFound = ReadFromFile( interfacePath, interfaceValue, sizeof( interfaceValue ) ); + if( deviceFound ) + { + deviceFound = ( 0 == strncmp( interfaceValue, deviceString, stringLen ) ); + } + return deviceFound; +} + +static bool GetAlsaConfiguration( uint16_t subBufferSize, uint8_t *amountOfChannels, uint8_t *bitDepth ) +{ + if( NULL == amountOfChannels || NULL == bitDepth ) + { + ConsolePrintf( PRIO_ERROR, RED"GetAlsaConfiguration was called with invalid parameters"RESETCOLOR"\n" ); + return false; + } + switch( subBufferSize ) + { + case 2: + *amountOfChannels = 1; + *bitDepth = 16; + break; + case 4: + *amountOfChannels = 2; + *bitDepth = 16; + break; + case 6: + *amountOfChannels = 2; + *bitDepth = 24; + break; + case 8: + *amountOfChannels = 2; + *bitDepth = 32; + break; + case 12: + *amountOfChannels = 6; + *bitDepth = 16; + break; + case 18: + *amountOfChannels = 6; + *bitDepth = 24; + break; + case 16: + *amountOfChannels = 8; + *bitDepth = 16; + break; + case 24: + *amountOfChannels = 8; + *bitDepth = 24; + break; + default: + ConsolePrintf( PRIO_ERROR, RED"Configure ALSA device was called"\ + " with unknown sub-buffer size: %d"RESETCOLOR"\n", subBufferSize ); + return false; + } + return true; +} + +bool ExistsUsbDeviceInstance( uint8_t deviceInstance ) +{ + uint32_t i; + bool found = false; + uint8_t curDevInst = 0; + char lastDescr[64]; + lastDescr[0] = '\0'; + for( i = 0; i < 12; i++ ) + { + uint32_t curDescrLen; + char curDescr[64]; + if( !ExistsDeviceWithType( i, "usb", 3 ) ) + continue; + + if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) ) + continue; + + curDescrLen = strnlen( curDescr, sizeof( curDescr ) ); + if( curDescrLen <= 2 ) + continue; + + //Cut away the last two characters, as they are different for the 3 interfaces of INIC + curDescrLen -= 2; + + if( 0 == strncmp( curDescr, lastDescr, curDescrLen ) ) + continue; + + strncpy( lastDescr, curDescr, curDescrLen ); + lastDescr[curDescrLen] = '\0'; + + if( curDevInst++ != deviceInstance ) + continue; + + found = true; + break; + } + return found; +} + +bool ExistsMlbDeviceInstance( uint8_t deviceInstance ) +{ + return ExistsDeviceWithType( deviceInstance, "mlb", 3 ); +} + +bool ExistsI2CDeviceInstance( uint8_t deviceInstance ) +{ + return ExistsDeviceWithType( deviceInstance, "i2c", 3 ); +} + +bool GetUsbDeviceNames( uint8_t deviceInstance, uint8_t endpointAddress, char *deviceName, uint16_t deviceNameLength, + char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength ) +{ + uint32_t i; + bool systemFound = false; + uint8_t curDevInst = 0; + char lastDescr[64]; + lastDescr[0] = '\0'; + char endpointBuffer[16]; + char systemSourceDir[64]; + DIR *d; + struct dirent *dir; + + if( NULL == deviceName || NULL == systemName || NULL == linkName ) + return false; + + deviceName[0] = '\0'; + systemName[0] = '\0'; + + for( i = 0; !systemFound && i < 12; i++ ) + { + uint32_t curDescrLen; + char curDescr[64]; + if( !ExistsDeviceWithType( i, "usb", 3 ) ) + continue; + + if( !GetDeviceDescription( i, curDescr, sizeof( curDescr ) ) ) + continue; + + curDescrLen = strnlen( curDescr, sizeof( curDescr ) ); + if( curDescrLen <= 2 ) + continue; + + //Cut away the last two characters, as they are different for the 3 interfaces of INIC + curDescrLen -= 2; + + if( ( '\0' != lastDescr[0] ) + && ( 0 != strncmp( curDescr, lastDescr, curDescrLen ) ) ) + { + ++curDevInst; + } + + strncpy( lastDescr, curDescr, curDescrLen ); + lastDescr[curDescrLen] = '\0'; + + if( curDevInst < deviceInstance ) + continue; + else if( curDevInst > deviceInstance ) + break; + + snprintf( endpointBuffer, sizeof( endpointBuffer ), "ep%02x", endpointAddress ); + snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d", i ); + d = opendir( systemSourceDir ); + if( d ) + { + while( ( dir = readdir( d ) ) != NULL ) + { + if( strstr( dir->d_name, endpointBuffer ) ) + { + snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name ); + snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name ); + snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", i, dir->d_name, deviceInstance, + dir->d_name ); + systemFound = true; + break; + } + } + closedir( d ); + } + } + return systemFound; +} + +bool GetMlbDeviceNames( uint8_t deviceInstance, uint8_t mlbChannelAddress, char *deviceName, uint16_t deviceNameLength, + char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength ) +{ + bool systemFound = false; + char channelBuffer[16]; + char systemSourceDir[64]; + DIR *d; + struct dirent *dir; + + if( NULL == deviceName || NULL == systemName || NULL == linkName ) + return false; + + deviceName[0] = '\0'; + systemName[0] = '\0'; + + snprintf( channelBuffer, sizeof( channelBuffer ), "ca%d", mlbChannelAddress ); + snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d", + deviceInstance ); + d = opendir( systemSourceDir ); + if( d ) + { + while( ( dir = readdir( d ) ) != NULL ) + { + if( strstr( dir->d_name, channelBuffer ) ) + { + snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name ); + snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name ); + snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance, + dir->d_name ); + systemFound = true; + break; + } + } + closedir( d ); + } + return systemFound; +} + +bool GetI2CDeviceNames( uint8_t deviceInstance, bool isTx, char *deviceName, uint16_t deviceNameLength, + char *systemName, uint16_t systemNameLength, char *linkName, uint16_t linkNameLength ) +{ + bool systemFound = false; + char systemSourceDir[64]; + DIR *d; + struct dirent *dir; + + if( NULL == deviceName || NULL == systemName || NULL == linkName ) + return false; + + deviceName[0] = '\0'; + systemName[0] = '\0'; + + snprintf( systemSourceDir, sizeof( systemSourceDir ), "/sys/devices/virtual/most/mostcore/devices/mdev%d", + deviceInstance ); + d = opendir( systemSourceDir ); + if( d ) + { + while( ( dir = readdir( d ) ) != NULL ) + { + if( strstr( dir->d_name, ( isTx ? "tx" : "rx" ) ) ) + { + snprintf( systemName, systemNameLength, "%s/%s", systemSourceDir, dir->d_name ); + snprintf( deviceName, deviceNameLength, "/dev/mdev%d-%s", deviceInstance, dir->d_name ); + snprintf( linkName, linkNameLength, "mdev%d:%s:mdev%d-%s", deviceInstance, dir->d_name, deviceInstance, + dir->d_name ); + systemFound = true; + break; + } + } + closedir( d ); + } + return systemFound; +} + +bool CloseMostChannel( const char *device ) +{ + return true; +} + +bool ConfigureMostChannel( const char *device, EPDataType_t mostType, EPDirection_t direction, uint32_t numBuf, + uint32_t bufSize ) +{ + static const char *controlType = "control"; + static const char *asyncType = "async"; + static const char *syncType = "sync"; + static const char *isocType = "isoc_avp"; + static const char *rxDirection = "dir_rx"; + static const char *txDirection = "dir_tx"; + bool success = true; + char tempBuffer[128]; + const char *typeString = NULL; + const char *directionString = NULL; + + switch( mostType ) + { + case EP_Control: + typeString = controlType; + break; + case EP_Asynchron: + typeString = asyncType; + break; + case EP_Synchron: + typeString = syncType; + break; + case EP_Isochron: + typeString = isocType; + break; + default: + return false; + } + + switch( direction ) + { + case EPDIR_IN: + directionString = txDirection; + break; + case EPDIR_OUT: + directionString = rxDirection; + break; + default: + return false; + } + + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_datatype", device ); /// Setting data type + success = WriteCharactersToFile( tempBuffer, typeString ); + if( success ) + { + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_direction", device ); /// Setting direction + success = WriteCharactersToFile( tempBuffer, directionString ); + } + if( success ) + { + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_number_of_buffers", device ); /// Setting amount of buffers + success = WriteIntegerToFile( tempBuffer, numBuf ); + } + if( success ) + { + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_buffer_size", device ); /// Setting amount of buffers + success = WriteIntegerToFile( tempBuffer, bufSize ); + } + return success; +} + +bool ConfigureIsocChannel( const char *device, uint32_t subbufferSize, uint32_t packetsPerTransaction ) +{ + char tempBuffer[128]; + bool success; + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the subbuffer size in bytes + success = WriteIntegerToFile( tempBuffer, subbufferSize ); + + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the packets per transaction + success = WriteIntegerToFile( tempBuffer, ( packetsPerTransaction & 0xFF ) ); + return success; +} + +bool ConfigureSyncChannel( const char *device, uint32_t syncBlockWidth, uint32_t amounOfSyncFrames ) +{ + char tempBuffer[128]; + bool success; + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_packets_per_xact", device ); /// Setting the amount of frames in one USB frame + success = WriteIntegerToFile( tempBuffer, amounOfSyncFrames ); + + snprintf( tempBuffer, sizeof( tempBuffer ), "%s/set_subbuffer_size", device ); /// Setting the blockwidth of a single frame + success = WriteIntegerToFile( tempBuffer, syncBlockWidth ); + return success; +} + +bool LinkToCharacterDevice( const char *linkName, const char *deviceName ) +{ + bool success = + WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/cdev/add_link", linkName ); + if( success ) + { + success = WaitForDevice( deviceName ); + } + if( success ) + { + chmod( deviceName, ( S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH ) ); + } + return success; +} + +bool LinkToAudioDevice( const char *linkName, uint16_t subBufferSize ) +{ + char tempBuffer[128]; + uint8_t amountOfChannels; + uint8_t bitDepth; + if( !GetAlsaConfiguration( subBufferSize, &amountOfChannels, &bitDepth ) ) + return false; + + snprintf( tempBuffer, sizeof( tempBuffer ), "%s.%dx%d", linkName, amountOfChannels, bitDepth ); /// Add the channel information behind the Link Name + + //Be compatible to all versions of MOST Linux Driver. The name was changed of Sound AIM. + bool success = + WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/sound/add_link", tempBuffer ); + if( !success ) + success = + WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/audio/add_link", tempBuffer ); + return success; +} + +bool LinkToVideoForLinuxDevice( const char *linkName ) +{ + bool success = + WriteCharactersToFile( "/sys/devices/virtual/most/mostcore/aims/v4l/add_link", linkName ); + return success; +} + +const char *GetErrnoString() +{ + switch( errno ) + { + case 0: + return "Nothing stored in errno"; + case 1: + return "Operation not permitted"; + case 2: + return "No such file or directory"; + case 3: + return "No such process"; + case 4: + return "Interrupted system call"; + case 5: + return "I/O error"; + case 6: + return "No such device or address"; + case 7: + return "Argument list too long"; + case 8: + return "Exec format error"; + case 9: + return "Bad file number"; + case 10: + return "No child processes"; + case 11: + return "Try again"; + case 12: + return "Out of memory"; + case 13: + return "Permission denied"; + case 14: + return "Bad address"; + case 15: + return "Block device required"; + case 16: + return "Device or resource busy"; + case 17: + return "File exists"; + case 18: + return "Cross-device link"; + case 19: + return "No such device"; + case 20: + return "Not a directory"; + case 21: + return "Is a directory"; + case 22: + return "Invalid argument"; + case 23: + return "File table overflow"; + case 24: + return "Too many open files"; + case 25: + return "Not a typewriter"; + case 26: + return "Text file busy"; + case 27: + return "File too large"; + case 28: + return "No space left on device"; + case 29: + return "Illegal seek"; + case 30: + return "Read-only file system"; + case 31: + return "Too many links"; + case 32: + return "Broken pipe"; + case 33: + return "Math argument out of domain of func"; + case 34: + return "Math result not representable"; + default: + break; + } + return "Unknown"; +} |