@@ -517,34 +517,102 @@ AccelerometerDevice::GetData(
517517
518518 SENSOR_FunctionEnter ();
519519
520+ //
521+ // Read sensor data safely using the EC busy bit and sample ID protocol.
522+ // The EC sets the busy bit while updating sensor data and increments the
523+ // sample ID (lower 4 bits of ACC_STATUS) after each update. We must:
524+ // 1. Wait for the busy bit to clear
525+ // 2. Record the sample ID
526+ // 3. Read all sensor data
527+ // 4. Re-read ACC_STATUS and verify the busy bit is still clear
528+ // and the sample ID hasn't changed
529+ // This guarantees we didn't read partially-updated data.
530+ //
520531 UINT8 acc_status = 0 ;
521- CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_STATUS, &acc_status);
522- TraceInformation (" Status: (%02x), Present: %d, Busy: %d\n " ,
523- acc_status,
524- (acc_status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT) > 0 ,
525- (acc_status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) > 0 );
532+ UINT8 samp_id = 0xFF ;
533+ UINT8 status = 0 ;
534+ int attempts = 0 ;
535+
536+ #define quarter (0xFFFF /4 )
537+ #define MAX_SENSOR_READ_ATTEMPTS 5
538+ #define MAX_BUSY_WAIT_ATTEMPTS 50
539+ #define BUSY_WAIT_SLEEP_INTERVAL 5
540+ #define BUSY_WAIT_SLEEP_MS 25
526541
527542 UINT8 lid_angle_bytes[2 ] = {0 };
528- CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_DATA + 0 , &lid_angle_bytes[0 ]);
529- CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_DATA + 1 , &lid_angle_bytes[1 ]);
530- UINT16 lid_angle = lid_angle_bytes[0 ] + (lid_angle_bytes[1 ] << 8 );
543+ UINT16 lid_angle = 0 ;
544+ UINT SensorOffset = 6 * m_LidSensorIndex + EC_MEMMAP_ACC_DATA + 2 ;
545+ UINT8 Sensor1[6 ] = {0 };
546+
547+ while ((status & (EC_MEMMAP_ACC_STATUS_BUSY_BIT |
548+ EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK)) != samp_id) {
549+
550+ if (attempts++ >= MAX_SENSOR_READ_ATTEMPTS) {
551+ TraceError (" %!FUNC! Failed to get consistent sensor data after %d attempts" , attempts);
552+ Status = STATUS_IO_DEVICE_ERROR;
553+ goto Exit;
554+ }
555+
556+ //
557+ // Poll ACC_STATUS until the EC is not busy
558+ //
559+ int busy_attempts = 0 ;
560+ CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_STATUS, &acc_status);
561+
562+ while (acc_status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) {
563+ if (busy_attempts++ >= MAX_BUSY_WAIT_ATTEMPTS) {
564+ TraceError (" %!FUNC! EC busy bit stuck after %d attempts" , busy_attempts);
565+ Status = STATUS_IO_DEVICE_ERROR;
566+ goto Exit;
567+ }
568+
569+ if (busy_attempts % BUSY_WAIT_SLEEP_INTERVAL == 0 )
570+ Sleep (BUSY_WAIT_SLEEP_MS);
571+
572+ CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_STATUS, &acc_status);
573+ }
574+
575+ TraceInformation (" Status: (%02x), Present: %d, Busy: %d\n " ,
576+ acc_status,
577+ (acc_status & EC_MEMMAP_ACC_STATUS_PRESENCE_BIT) > 0 ,
578+ (acc_status & EC_MEMMAP_ACC_STATUS_BUSY_BIT) > 0 );
579+
580+ //
581+ // Record the current sample ID before reading data
582+ //
583+ samp_id = acc_status & EC_MEMMAP_ACC_STATUS_SAMPLE_ID_MASK;
584+
585+ //
586+ // Read all sensor data (unsafe - EC could update mid-read)
587+ //
588+ CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_DATA + 0 , &lid_angle_bytes[0 ]);
589+ CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_DATA + 1 , &lid_angle_bytes[1 ]);
590+
591+ CrosEcReadMemU8 (Handle, SensorOffset + 0 , &Sensor1[0 ]);
592+ CrosEcReadMemU8 (Handle, SensorOffset + 1 , &Sensor1[1 ]);
593+ CrosEcReadMemU8 (Handle, SensorOffset + 2 , &Sensor1[2 ]);
594+ CrosEcReadMemU8 (Handle, SensorOffset + 3 , &Sensor1[3 ]);
595+ CrosEcReadMemU8 (Handle, SensorOffset + 4 , &Sensor1[4 ]);
596+ CrosEcReadMemU8 (Handle, SensorOffset + 5 , &Sensor1[5 ]);
597+
598+ //
599+ // Re-read ACC_STATUS to verify data consistency
600+ //
601+ CrosEcReadMemU8 (Handle, EC_MEMMAP_ACC_STATUS, &status);
602+ }
603+
604+ //
605+ // Data is now consistent - process it
606+ //
607+ lid_angle = lid_angle_bytes[0 ] + (lid_angle_bytes[1 ] << 8 );
531608 TraceInformation (" Lid Angle Status: %dDeg%s" , lid_angle, lid_angle == 500 ? " (Unreliable)" : " " );
532609
533610 // Lid accelerometer is relevant for screen rotation
534611 // Base accelerometer is not used in this driver
535612 // It's only used for lid angle in the EC firmware
536- UINT SensorOffset = 6 * m_LidSensorIndex + EC_MEMMAP_ACC_DATA + 2 ;
537- UINT16 Sensor1[6 ] = {0 };
538- CrosEcReadMemU8 (Handle, SensorOffset, (UINT8*)&Sensor1[0 ]);
539- CrosEcReadMemU8 (Handle, SensorOffset + 1 , (UINT8*)&Sensor1[1 ]);
540- CrosEcReadMemU8 (Handle, SensorOffset + 2 , (UINT8*)&Sensor1[2 ]);
541- CrosEcReadMemU8 (Handle, SensorOffset + 3 , (UINT8*)&Sensor1[3 ]);
542- CrosEcReadMemU8 (Handle, SensorOffset + 4 , (UINT8*)&Sensor1[4 ]);
543- CrosEcReadMemU8 (Handle, SensorOffset + 5 , (UINT8*)&Sensor1[5 ]);
544613 m_CachedData.Axis .X = (float ) (Sensor1[0 ] + (Sensor1[1 ] << 8 ));
545614 m_CachedData.Axis .Y = (float ) (Sensor1[2 ] + (Sensor1[3 ] << 8 ));
546615 m_CachedData.Axis .Z = (float ) (Sensor1[4 ] + (Sensor1[5 ] << 8 ));
547- #define quarter (0xFFFF /4 )
548616 m_CachedData.Axis .X = -((float ) (INT16) m_CachedData.Axis .X ) / quarter;
549617 m_CachedData.Axis .Y = -((float ) (INT16) m_CachedData.Axis .Y ) / quarter;
550618 m_CachedData.Axis .Z = -((float ) (INT16) m_CachedData.Axis .Z ) / quarter;
@@ -610,6 +678,7 @@ AccelerometerDevice::GetData(
610678 TraceInformation (" COMBO %!FUNC! LAC Data did NOT meet the threshold" );
611679 }
612680
681+ Exit:
613682 SENSOR_FunctionExit (Status);
614683 return Status;
615684}
0 commit comments