summaryrefslogtreecommitdiffstats
path: root/Src/Network/base/DriverConfiguration.c
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Network/base/DriverConfiguration.c')
-rw-r--r--Src/Network/base/DriverConfiguration.c608
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";
+}