312 lines
8.5 KiB
C
312 lines
8.5 KiB
C
|
#include <stdarg.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#include "rpiHardware.h"
|
||
|
#include "rpi-mailbox.h"
|
||
|
#include "rpi-mailbox-interface.h"
|
||
|
|
||
|
/* Make sure the property tag buffer is aligned to a 16-byte boundary because
|
||
|
we only have 28-bits available in the property interface protocol to pass
|
||
|
the address of the buffer to the VC. */
|
||
|
static int pt[PROP_BUFFER_SIZE] __attribute__((aligned(16)));
|
||
|
static int pt_index = 0;
|
||
|
|
||
|
//#define PRINT_PROP_DEBUG 1
|
||
|
|
||
|
void RPI_PropertyInit( void )
|
||
|
{
|
||
|
//memset(pt, 0, sizeof(pt));
|
||
|
|
||
|
/* Fill in the size on-the-fly */
|
||
|
pt[PT_OSIZE] = 12;
|
||
|
|
||
|
/* Process request (All other values are reserved!) */
|
||
|
pt[PT_OREQUEST_OR_RESPONSE] = 0;
|
||
|
|
||
|
/* First available data slot */
|
||
|
pt_index = 2;
|
||
|
|
||
|
/* NULL tag to terminate tag list */
|
||
|
pt[pt_index] = 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
@brief Add a property tag to the current tag list. Data can be included. All data is uint32_t
|
||
|
@param tag
|
||
|
*/
|
||
|
void RPI_PropertyAddTag( rpi_mailbox_tag_t tag, ... )
|
||
|
{
|
||
|
int* ptr;
|
||
|
int value;
|
||
|
va_list vl;
|
||
|
va_start( vl, tag );
|
||
|
|
||
|
pt[pt_index++] = tag;
|
||
|
|
||
|
switch( tag )
|
||
|
{
|
||
|
case TAG_GET_FIRMWARE_VERSION:
|
||
|
case TAG_GET_BOARD_MODEL:
|
||
|
case TAG_GET_BOARD_REVISION:
|
||
|
case TAG_GET_BOARD_MAC_ADDRESS:
|
||
|
case TAG_GET_BOARD_SERIAL:
|
||
|
case TAG_GET_ARM_MEMORY:
|
||
|
case TAG_GET_VC_MEMORY:
|
||
|
case TAG_GET_DMA_CHANNELS:
|
||
|
/* Provide an 8-byte buffer for the response */
|
||
|
pt[pt_index++] = 8;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt_index += 2;
|
||
|
break;
|
||
|
|
||
|
case TAG_GET_CLOCKS:
|
||
|
case TAG_GET_COMMAND_LINE:
|
||
|
/* Provide a 1024-byte buffer */
|
||
|
pt[pt_index++] = PROP_SIZE;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt_index += PROP_SIZE >> 2;
|
||
|
break;
|
||
|
|
||
|
case TAG_GET_CLOCK_RATE:
|
||
|
case TAG_GET_MAX_CLOCK_RATE:
|
||
|
case TAG_GET_MIN_CLOCK_RATE:
|
||
|
case TAG_GET_TURBO:
|
||
|
case TAG_GET_TEMPERATURE:
|
||
|
case TAG_GET_MAX_TEMPERATURE:
|
||
|
case TAG_GET_VOLTAGE:
|
||
|
case TAG_GET_MIN_VOLTAGE:
|
||
|
case TAG_GET_MAX_VOLTAGE:
|
||
|
pt[pt_index++] = 8;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* ClockID */
|
||
|
pt_index += 1;
|
||
|
break;
|
||
|
|
||
|
case TAG_EXECUTE_CODE:
|
||
|
pt[pt_index++] = 28;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt[pt_index++] = va_arg( vl, int ); // Function pointer
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R0
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R1
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R2
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R3
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R4
|
||
|
pt[pt_index++] = va_arg( vl, int ); // R5
|
||
|
break;
|
||
|
|
||
|
case TAG_ALLOCATE_BUFFER:
|
||
|
pt[pt_index++] = 8;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt[pt_index++] = va_arg( vl, int );
|
||
|
pt_index += 1;
|
||
|
break;
|
||
|
|
||
|
case TAG_GET_PHYSICAL_SIZE:
|
||
|
case TAG_SET_PHYSICAL_SIZE:
|
||
|
case TAG_TEST_PHYSICAL_SIZE:
|
||
|
case TAG_GET_VIRTUAL_SIZE:
|
||
|
case TAG_SET_VIRTUAL_SIZE:
|
||
|
case TAG_TEST_VIRTUAL_SIZE:
|
||
|
case TAG_GET_VIRTUAL_OFFSET:
|
||
|
case TAG_SET_VIRTUAL_OFFSET:
|
||
|
pt[pt_index++] = 8;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
|
||
|
if( ( tag == TAG_SET_PHYSICAL_SIZE ) ||
|
||
|
( tag == TAG_SET_VIRTUAL_SIZE ) ||
|
||
|
( tag == TAG_SET_VIRTUAL_OFFSET ) ||
|
||
|
( tag == TAG_TEST_PHYSICAL_SIZE ) ||
|
||
|
( tag == TAG_TEST_VIRTUAL_SIZE ) )
|
||
|
{
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Width */
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Height */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pt_index += 2;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
case TAG_GET_ALPHA_MODE:
|
||
|
case TAG_SET_ALPHA_MODE:
|
||
|
case TAG_GET_DEPTH:
|
||
|
case TAG_SET_DEPTH:
|
||
|
case TAG_GET_PIXEL_ORDER:
|
||
|
case TAG_SET_PIXEL_ORDER:
|
||
|
case TAG_GET_PITCH:
|
||
|
pt[pt_index++] = 4;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
|
||
|
if( ( tag == TAG_SET_DEPTH ) ||
|
||
|
( tag == TAG_SET_PIXEL_ORDER ) ||
|
||
|
( tag == TAG_SET_ALPHA_MODE ) )
|
||
|
{
|
||
|
/* Colour Depth, bits-per-pixel \ Pixel Order State */
|
||
|
pt[pt_index++] = va_arg( vl, int );
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pt_index += 1;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TAG_GET_OVERSCAN:
|
||
|
case TAG_SET_OVERSCAN:
|
||
|
pt[pt_index++] = 16;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
|
||
|
if( ( tag == TAG_SET_OVERSCAN ) )
|
||
|
{
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Top pixels */
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Bottom pixels */
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Left pixels */
|
||
|
pt[pt_index++] = va_arg( vl, int ); /* Right pixels */
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pt_index += 4;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case TAG_SET_POWER_STATE:
|
||
|
case TAG_GET_POWER_STATE:
|
||
|
pt[pt_index++] = 8;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
if ((tag == TAG_SET_POWER_STATE))
|
||
|
{
|
||
|
pt[pt_index++] = va_arg(vl, int); // deviceID
|
||
|
pt[pt_index++] = va_arg(vl, int); // state
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
pt_index += 2;
|
||
|
}
|
||
|
pt_index += 1;
|
||
|
|
||
|
break;
|
||
|
|
||
|
case TAG_SET_PALETTE:
|
||
|
ptr = va_arg(vl, int*);
|
||
|
value = ptr[1]; // number of palette entries
|
||
|
pt[pt_index++] = 8 + value * 4;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt[pt_index++] = *ptr++; // first palette index
|
||
|
// value = *ptr++; // number of palette entries
|
||
|
ptr++;
|
||
|
pt[pt_index++] = value;
|
||
|
{
|
||
|
for (int index = 0; index < value; ++index)
|
||
|
{
|
||
|
pt[pt_index++] = *ptr++;
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
|
||
|
//Set the PWR led signal to output mode, allowing to control it : rpi3 - gpiovirtbuf c 135 1 0 0 0 0
|
||
|
//Set the PWR led off : rpi3 - gpiovirtbuf s 135 0
|
||
|
|
||
|
//GPIO 134 is the camera LED GPIO
|
||
|
//GPIO 133 is the camera power GPIO
|
||
|
|
||
|
case TAG_GET_GPIOVIRTBUF:
|
||
|
case TAG_GET_TOUCHBUF:
|
||
|
pt[pt_index++] = 4;
|
||
|
pt[pt_index++] = 0; /* Request */
|
||
|
pt_index += 1;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* Unsupported tags, just remove the tag from the list */
|
||
|
pt_index--;
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Make sure the tags are 0 terminated to end the list and update the buffer size */
|
||
|
pt[pt_index] = 0;
|
||
|
|
||
|
va_end( vl );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
int RPI_PropertyProcess( void )
|
||
|
{
|
||
|
int result;
|
||
|
|
||
|
#if( PRINT_PROP_DEBUG == 1 )
|
||
|
int i;
|
||
|
LOG_INFO( "%s Length: %d\r\n", __func__, pt[PT_OSIZE] );
|
||
|
#endif
|
||
|
/* Fill in the size of the buffer */
|
||
|
pt[PT_OSIZE] = ( pt_index + 1 ) << 2;
|
||
|
pt[PT_OREQUEST_OR_RESPONSE] = 0;
|
||
|
|
||
|
#if( PRINT_PROP_DEBUG == 1 )
|
||
|
for( i = 0; i < (pt[PT_OSIZE] >> 2); i++ )
|
||
|
LOG_INFO( "Request: %3d %8.8X\r\n", i, pt[i] );
|
||
|
#endif
|
||
|
RPI_Mailbox0Write(MB0_TAGS_ARM_TO_VC, (unsigned int)pt);
|
||
|
|
||
|
result = RPI_Mailbox0Read( MB0_TAGS_ARM_TO_VC );
|
||
|
|
||
|
#if( PRINT_PROP_DEBUG == 1 )
|
||
|
for( i = 0; i < (pt[PT_OSIZE] >> 2); i++ )
|
||
|
LOG_INFO( "Response: %3d %8.8X\r\n", i, pt[i] );
|
||
|
#endif
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
void RPI_PropertyProcessNoCheck( void )
|
||
|
{
|
||
|
#if( PRINT_PROP_DEBUG == 1 )
|
||
|
int i;
|
||
|
LOG_INFO( "%s Length: %d\r\n", __func__, pt[PT_OSIZE] );
|
||
|
#endif
|
||
|
/* Fill in the size of the buffer */
|
||
|
pt[PT_OSIZE] = ( pt_index + 1 ) << 2;
|
||
|
pt[PT_OREQUEST_OR_RESPONSE] = 0;
|
||
|
|
||
|
#if( PRINT_PROP_DEBUG == 1 )
|
||
|
for( i = 0; i < (pt[PT_OSIZE] >> 2); i++ )
|
||
|
LOG_INFO( "Request: %3d %8.8X\r\n", i, pt[i] );
|
||
|
#endif
|
||
|
RPI_Mailbox0Write( MB0_TAGS_ARM_TO_VC, (unsigned int)pt );
|
||
|
}
|
||
|
|
||
|
rpi_mailbox_property_t* RPI_PropertyGet( rpi_mailbox_tag_t tag)
|
||
|
{
|
||
|
static rpi_mailbox_property_t property;
|
||
|
int* tag_buffer = NULL;
|
||
|
|
||
|
property.tag = tag;
|
||
|
|
||
|
/* Get the tag from the buffer. Start at the first tag position */
|
||
|
int index = 2;
|
||
|
|
||
|
while( index < ( pt[PT_OSIZE] >> 2 ) )
|
||
|
{
|
||
|
/* DEBUG_LOG( "Test Tag: [%d] %8.8X\r\n", index, pt[index] ); */
|
||
|
if( pt[index] == tag )
|
||
|
{
|
||
|
tag_buffer = &pt[index];
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
/* Progress to the next tag if we haven't yet discovered the tag */
|
||
|
index += ( pt[index + 1] >> 2 ) + 3;
|
||
|
}
|
||
|
|
||
|
/* Return NULL of the property tag cannot be found in the buffer */
|
||
|
if( tag_buffer == NULL )
|
||
|
return NULL;
|
||
|
|
||
|
/* Return the required data */
|
||
|
property.byte_length = tag_buffer[T_ORESPONSE] & 0xFFFF;
|
||
|
memcpy( property.data.buffer_8, &tag_buffer[T_OVALUE], property.byte_length );
|
||
|
|
||
|
return &property;
|
||
|
}
|