Reorganize BBeOS project structure for better maintainability
Some checks failed
CI / markdown-lint (push) Failing after 14s
Some checks failed
CI / markdown-lint (push) Failing after 14s
- Reorganized directory structure following open source best practices - Created src/ directory for all source code components - Moved build artifacts to build/ subdirectories - Organized documentation into phases/, guides/, and api/ subdirectories - Moved third-party code to vendor/ directory - Moved downloads to downloads/ directory - Updated all build scripts to reference new directory structure - Created comprehensive PROJECT_STRUCTURE.md documentation - Added DEVELOPMENT_GUIDE.md as main entry point - Improved separation of concerns and maintainability - Follows standard open source project conventions
This commit is contained in:
281
PROJECT_STRUCTURE.md
Normal file
281
PROJECT_STRUCTURE.md
Normal file
@ -0,0 +1,281 @@
|
||||
# BBeOS Project Structure
|
||||
|
||||
This document provides a comprehensive overview of the BBeOS project structure and organization.
|
||||
|
||||
## 📁 Directory Layout
|
||||
|
||||
```
|
||||
BBeOS/
|
||||
├── 📚 docs/ # Documentation
|
||||
│ ├── 📋 phases/ # Phase-by-phase development docs
|
||||
│ │ ├── PHASE_1_*.md # Research & Feasibility
|
||||
│ │ ├── PHASE_2_*.md # Bootstrapping
|
||||
│ │ ├── PHASE_3_*.md # Hardware Support
|
||||
│ │ ├── PHASE_4_*.md # User Interface
|
||||
│ │ ├── PHASE_5_*.md # Telephony Stack
|
||||
│ │ ├── PHASE_6_*.md # Packaging & Updates
|
||||
│ │ └── PHASE_7_*.md # Community & SDK
|
||||
│ ├── 📖 guides/ # How-to guides and tutorials
|
||||
│ │ ├── EMULATION_GUIDE.md # QEMU emulation guide
|
||||
│ │ └── hardware-testing-guide.md # Hardware testing guide
|
||||
│ ├── 🔧 api/ # API documentation and design docs
|
||||
│ │ ├── UI_UX_DESIGN.md # UI/UX design specifications
|
||||
│ │ └── SECURITY_ANALYSIS.md # Security analysis and recommendations
|
||||
│ └── DEVELOPMENT_GUIDE.md # Main development guide
|
||||
│
|
||||
├── 💻 src/ # Source code
|
||||
│ ├── 🖥️ kernel/ # Kernel configuration and patches
|
||||
│ │ └── msm8960-defconfig # MSM8960 kernel configuration
|
||||
│ ├── 🔌 drivers/ # Hardware drivers
|
||||
│ │ ├── display/ # Display drivers
|
||||
│ │ │ └── q20-panel.c # Q20 LCD panel driver
|
||||
│ │ ├── input/ # Input device drivers
|
||||
│ │ │ └── q20-keyboard.c # Q20 keyboard driver
|
||||
│ │ └── Makefile # Driver build configuration
|
||||
│ ├── 🖼️ ui/ # User interface components
|
||||
│ │ ├── compositor/ # Wayland compositor
|
||||
│ │ │ └── q20-compositor.c # Q20-specific compositor
|
||||
│ │ ├── applications/ # UI applications
|
||||
│ │ │ └── home-screen.c # Home screen application
|
||||
│ │ └── Makefile # UI build configuration
|
||||
│ ├── 📞 telephony/ # Phone functionality
|
||||
│ │ ├── modem/ # Modem drivers
|
||||
│ │ │ └── q20-modem.c # MDM9615 modem driver
|
||||
│ │ ├── voice/ # Voice call management
|
||||
│ │ │ └── q20-voice.c # Voice call driver
|
||||
│ │ ├── sms/ # SMS management
|
||||
│ │ │ └── q20-sms.c # SMS driver
|
||||
│ │ └── Makefile # Telephony build configuration
|
||||
│ ├── 📱 apps/ # Core applications
|
||||
│ │ ├── core/ # Core system apps
|
||||
│ │ │ ├── calculator.c # Calculator application
|
||||
│ │ │ └── text-editor.c # Text editor application
|
||||
│ │ └── Makefile # Application build configuration
|
||||
│ ├── 🛠️ sdk/ # Development tools and SDK
|
||||
│ │ └── tools/ # SDK tools
|
||||
│ │ └── bbeos-sdk.c # BBeOS SDK main tool
|
||||
│ └── 📦 packaging/ # System packaging and deployment
|
||||
│ ├── system/ # System image creation
|
||||
│ │ └── image-builder.c # System image builder
|
||||
│ ├── security/ # Security components
|
||||
│ │ └── secure-boot.c # Secure boot implementation
|
||||
│ ├── updates/ # Update system
|
||||
│ │ └── ota-updater.c # OTA update system
|
||||
│ └── Makefile # Packaging build configuration
|
||||
│
|
||||
├── 🔨 build/ # Build artifacts
|
||||
│ ├── 🖥️ kernel/ # Kernel builds
|
||||
│ │ ├── zImage # Kernel image
|
||||
│ │ ├── *.dtb # Device tree blobs
|
||||
│ │ └── modules/ # Kernel modules
|
||||
│ ├── 📁 rootfs/ # Root filesystem
|
||||
│ │ ├── bin/ # Binary files
|
||||
│ │ ├── etc/ # Configuration files
|
||||
│ │ ├── lib/ # Library files
|
||||
│ │ └── init # Init script
|
||||
│ ├── 🖼️ images/ # Boot images
|
||||
│ │ ├── bbeos-boot.img # Bootable system image
|
||||
│ │ ├── initramfs.img # Initial RAM filesystem
|
||||
│ │ └── recovery.img # Recovery image
|
||||
│ ├── 🖼️ ui/ # UI build artifacts
|
||||
│ │ ├── compositor/ # Compiled compositor
|
||||
│ │ ├── applications/ # Compiled applications
|
||||
│ │ └── assets/ # UI assets
|
||||
│ └── 📦 boot-unpacked/ # Unpacked boot components
|
||||
│
|
||||
├── 🔧 scripts/ # Build automation and tools
|
||||
│ ├── build-kernel.sh # Full kernel build script
|
||||
│ ├── build-kernel-minimal.sh # Minimal kernel build script
|
||||
│ ├── build-rootfs.sh # Root filesystem build script
|
||||
│ ├── build-boot-image.sh # Boot image creation script
|
||||
│ ├── build-drivers.sh # Driver build script
|
||||
│ ├── build-ui.sh # UI build script
|
||||
│ ├── build-telephony.sh # Telephony build script
|
||||
│ ├── build-packaging.sh # Packaging build script
|
||||
│ ├── emulate-simple.sh # Simple QEMU emulation
|
||||
│ ├── emulate-bbeos.sh # Full BBeOS emulation
|
||||
│ ├── emulate-terminal.sh # Terminal-based simulation
|
||||
│ ├── hardware-test.sh # Hardware testing script
|
||||
│ ├── flash-boot.sh # Device flashing script
|
||||
│ ├── test-qemu.sh # QEMU testing script
|
||||
│ └── test-qemu-compatible.sh # Compatible QEMU testing
|
||||
│
|
||||
├── 🧪 tests/ # Test files and test automation
|
||||
│ ├── unit/ # Unit tests
|
||||
│ ├── integration/ # Integration tests
|
||||
│ └── hardware/ # Hardware tests
|
||||
│
|
||||
├── 📦 vendor/ # Third-party code and dependencies
|
||||
│ └── kernel-source/ # Linux kernel source
|
||||
│ ├── arch/arm/boot/dts/qcom/ # Qualcomm device trees
|
||||
│ └── ... # Other kernel files
|
||||
│
|
||||
├── 📥 downloads/ # External downloads and sources
|
||||
│ ├── busybox-1.36.1/ # BusyBox source
|
||||
│ ├── busybox-1.36.1.tar.bz2 # BusyBox archive
|
||||
│ └── ... # Other downloads
|
||||
│
|
||||
├── 🌐 community/ # Community website and resources
|
||||
│ └── website/ # Community website
|
||||
│ └── index.html # Main website page
|
||||
│
|
||||
├── 🔬 research/ # Hardware research and analysis
|
||||
│ ├── q20-hardware-research.md # Q20 hardware research
|
||||
│ ├── bootloader-analysis.md # Bootloader analysis
|
||||
│ ├── driver-compatibility.md # Driver compatibility research
|
||||
│ └── q20-specs.md # Q20 specifications
|
||||
│
|
||||
├── 📋 .gitea/ # Gitea configuration
|
||||
│ └── workflows/ # CI/CD workflows
|
||||
│ └── ci.yml # Continuous integration
|
||||
│
|
||||
├── 📄 Configuration Files
|
||||
│ ├── README.md # Project overview
|
||||
│ ├── QUICK_START.md # Quick start guide
|
||||
│ ├── PROJECT_STRUCTURE.md # This file
|
||||
│ ├── .gitignore # Git ignore rules
|
||||
│ ├── config.yaml # Gitea runner configuration
|
||||
│ └── bbeos-runner.service # Systemd service file
|
||||
│
|
||||
└── 🏗️ hardware/ # Hardware specifications
|
||||
└── q20-specs.md # BlackBerry Classic Q20 specs
|
||||
```
|
||||
|
||||
## 🎯 Organization Principles
|
||||
|
||||
### **1. Separation of Concerns**
|
||||
- **Source code** (`src/`) is separate from **build artifacts** (`build/`)
|
||||
- **Documentation** (`docs/`) is organized by type and purpose
|
||||
- **Scripts** (`scripts/`) handle automation and tooling
|
||||
- **Third-party code** (`vendor/`) is isolated from project code
|
||||
|
||||
### **2. Build System Organization**
|
||||
- **Build artifacts** are placed in `build/` subdirectories
|
||||
- **Downloads** are stored in `downloads/` directory
|
||||
- **Scripts** reference the new directory structure
|
||||
- **Clean separation** between source and build files
|
||||
|
||||
### **3. Documentation Structure**
|
||||
- **Phase documentation** in `docs/phases/`
|
||||
- **How-to guides** in `docs/guides/`
|
||||
- **API documentation** in `docs/api/`
|
||||
- **Main development guide** at `docs/DEVELOPMENT_GUIDE.md`
|
||||
|
||||
### **4. Source Code Organization**
|
||||
- **Kernel components** in `src/kernel/`
|
||||
- **Hardware drivers** in `src/drivers/`
|
||||
- **User interface** in `src/ui/`
|
||||
- **Telephony stack** in `src/telephony/`
|
||||
- **Applications** in `src/apps/`
|
||||
- **Development tools** in `src/sdk/`
|
||||
- **Packaging tools** in `src/packaging/`
|
||||
|
||||
## 🔄 Build Workflow
|
||||
|
||||
### **1. Kernel Build**
|
||||
```bash
|
||||
./scripts/build-kernel.sh # Full kernel build
|
||||
./scripts/build-kernel-minimal.sh # Minimal kernel build
|
||||
```
|
||||
- **Source**: `vendor/kernel-source/`
|
||||
- **Output**: `build/kernel/`
|
||||
|
||||
### **2. Root Filesystem**
|
||||
```bash
|
||||
./scripts/build-rootfs.sh # Build BusyBox rootfs
|
||||
```
|
||||
- **Source**: `downloads/busybox-*/`
|
||||
- **Output**: `build/rootfs/`
|
||||
|
||||
### **3. System Components**
|
||||
```bash
|
||||
./scripts/build-drivers.sh # Build hardware drivers
|
||||
./scripts/build-ui.sh # Build UI components
|
||||
./scripts/build-telephony.sh # Build telephony stack
|
||||
./scripts/build-packaging.sh # Build system images
|
||||
```
|
||||
- **Source**: `src/*/`
|
||||
- **Output**: `build/*/`
|
||||
|
||||
### **4. System Integration**
|
||||
```bash
|
||||
./scripts/build-boot-image.sh # Create bootable image
|
||||
```
|
||||
- **Input**: `build/kernel/`, `build/rootfs/`
|
||||
- **Output**: `build/images/`
|
||||
|
||||
## 🧪 Testing and Emulation
|
||||
|
||||
### **Emulation Options**
|
||||
```bash
|
||||
./scripts/emulate-simple.sh # Simple QEMU demo
|
||||
./scripts/emulate-bbeos.sh # Full BBeOS emulation
|
||||
./scripts/emulate-terminal.sh # Terminal-based simulation
|
||||
```
|
||||
|
||||
### **Hardware Testing**
|
||||
```bash
|
||||
./scripts/hardware-test.sh # Hardware component testing
|
||||
```
|
||||
|
||||
## 📚 Documentation Access
|
||||
|
||||
### **Main Guides**
|
||||
- **Development Guide**: `docs/DEVELOPMENT_GUIDE.md`
|
||||
- **Project Structure**: `PROJECT_STRUCTURE.md` (this file)
|
||||
- **Quick Start**: `QUICK_START.md`
|
||||
|
||||
### **Phase Documentation**
|
||||
- **Phase 1**: `docs/phases/PHASE_1_*.md` - Research & Feasibility
|
||||
- **Phase 2**: `docs/phases/PHASE_2_*.md` - Bootstrapping
|
||||
- **Phase 3**: `docs/phases/PHASE_3_*.md` - Hardware Support
|
||||
- **Phase 4**: `docs/phases/PHASE_4_*.md` - User Interface
|
||||
- **Phase 5**: `docs/phases/PHASE_5_*.md` - Telephony Stack
|
||||
- **Phase 6**: `docs/phases/PHASE_6_*.md` - Packaging & Updates
|
||||
- **Phase 7**: `docs/phases/PHASE_7_*.md` - Community & SDK
|
||||
|
||||
### **How-to Guides**
|
||||
- **Emulation**: `docs/guides/EMULATION_GUIDE.md`
|
||||
- **Hardware Testing**: `docs/guides/hardware-testing-guide.md`
|
||||
|
||||
### **API Documentation**
|
||||
- **UI/UX Design**: `docs/api/UI_UX_DESIGN.md`
|
||||
- **Security Analysis**: `docs/api/SECURITY_ANALYSIS.md`
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### **Build Configuration**
|
||||
- **Kernel config**: `src/kernel/msm8960-defconfig`
|
||||
- **Device tree**: `vendor/kernel-source/arch/arm/boot/dts/qcom/`
|
||||
- **Build artifacts**: `build/` directory structure
|
||||
|
||||
### **Environment Variables**
|
||||
- `CROSS_COMPILE`: ARM cross-compilation toolchain
|
||||
- `KERNEL_DIR`: Kernel source directory (`vendor/kernel-source`)
|
||||
- `BUILD_DIR`: Build output directory (`build/`)
|
||||
|
||||
## 🎯 Benefits of This Structure
|
||||
|
||||
### **1. Maintainability**
|
||||
- **Clear separation** between source, build, and documentation
|
||||
- **Consistent naming** conventions throughout
|
||||
- **Modular organization** for easy navigation
|
||||
|
||||
### **2. Scalability**
|
||||
- **Extensible structure** for new components
|
||||
- **Standard directories** for common project needs
|
||||
- **Build system** that scales with project growth
|
||||
|
||||
### **3. Developer Experience**
|
||||
- **Intuitive navigation** through logical organization
|
||||
- **Comprehensive documentation** at every level
|
||||
- **Clear build workflows** with dedicated scripts
|
||||
|
||||
### **4. Open Source Best Practices**
|
||||
- **Standard directory layout** following open source conventions
|
||||
- **Proper separation** of concerns
|
||||
- **Comprehensive documentation** structure
|
||||
|
||||
---
|
||||
|
||||
*This structure is designed to support the development of a complete operating system while maintaining clarity and organization for developers and contributors.*
|
||||
@ -1,14 +0,0 @@
|
||||
# BBeOS Boot Script
|
||||
# For testing with QEMU or other bootloaders
|
||||
|
||||
# Load kernel
|
||||
fatload mmc 0:1 0x80200000 zImage
|
||||
|
||||
# Load device tree
|
||||
fatload mmc 0:1 0x82000000 dtb
|
||||
|
||||
# Load initramfs
|
||||
fatload mmc 0:1 0x83000000 initramfs.img
|
||||
|
||||
# Boot kernel
|
||||
bootz 0x80200000 0x83000000 0x82000000
|
||||
Binary file not shown.
262
docs/DEVELOPMENT_GUIDE.md
Normal file
262
docs/DEVELOPMENT_GUIDE.md
Normal file
@ -0,0 +1,262 @@
|
||||
# BBeOS Development Guide
|
||||
|
||||
Welcome to the BBeOS development guide! This document serves as the main entry point for developers working on the BlackBerry Classic Linux OS project.
|
||||
|
||||
## 🎯 Project Overview
|
||||
|
||||
BBeOS is a lightweight, secure, non-Android, Linux-based operating system for the BlackBerry Classic (Q20) that transforms this iconic device into a modern, privacy-focused smartphone.
|
||||
|
||||
### Key Features
|
||||
- **Native Hardware Support**: Boot on ARMv7 architecture with full hardware integration
|
||||
- **Security-First Design**: Privacy-focused design with minimal attack surface
|
||||
- **Physical Interface Optimization**: GUI designed for trackpad navigation and physical QWERTY keyboard
|
||||
- **Core Telephony**: Complete phone functionality including calling, SMS, Wi-Fi, and GPS
|
||||
- **Open Source**: Community-driven development with transparent codebase
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
```
|
||||
BBeOS/
|
||||
├── docs/ # Documentation
|
||||
│ ├── phases/ # Phase-by-phase development docs
|
||||
│ ├── guides/ # How-to guides and tutorials
|
||||
│ └── api/ # API documentation and design docs
|
||||
├── src/ # Source code
|
||||
│ ├── kernel/ # Kernel configuration and patches
|
||||
│ ├── drivers/ # Hardware drivers
|
||||
│ ├── ui/ # User interface components
|
||||
│ ├── telephony/ # Phone functionality
|
||||
│ ├── apps/ # Core applications
|
||||
│ ├── sdk/ # Development tools and SDK
|
||||
│ └── packaging/ # System packaging and deployment
|
||||
├── build/ # Build artifacts
|
||||
│ ├── kernel/ # Kernel builds
|
||||
│ ├── rootfs/ # Root filesystem
|
||||
│ └── images/ # Boot images
|
||||
├── scripts/ # Build automation and tools
|
||||
├── tests/ # Test files and test automation
|
||||
├── vendor/ # Third-party code and dependencies
|
||||
├── downloads/ # External downloads and sources
|
||||
├── community/ # Community website and resources
|
||||
└── research/ # Hardware research and analysis
|
||||
```
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Linux development environment (Ubuntu 20.04+ recommended)
|
||||
- Cross-compilation toolchain for ARMv7
|
||||
- QEMU for emulation testing
|
||||
- Git for version control
|
||||
|
||||
### Building the System
|
||||
|
||||
1. **Clone the repository**:
|
||||
```bash
|
||||
git clone https://gitea.lab48.be/eliott/BBeOS.git
|
||||
cd BBeOS
|
||||
```
|
||||
|
||||
2. **Build the kernel**:
|
||||
```bash
|
||||
./scripts/build-kernel.sh
|
||||
```
|
||||
|
||||
3. **Build the root filesystem**:
|
||||
```bash
|
||||
./scripts/build-rootfs.sh
|
||||
```
|
||||
|
||||
4. **Create boot image**:
|
||||
```bash
|
||||
./scripts/build-boot-image.sh
|
||||
```
|
||||
|
||||
5. **Test in emulation**:
|
||||
```bash
|
||||
./scripts/emulate-simple.sh
|
||||
```
|
||||
|
||||
## 📋 Development Phases
|
||||
|
||||
The project is organized into 7 development phases:
|
||||
|
||||
### Phase 1: Research & Feasibility
|
||||
- Hardware specification analysis
|
||||
- Bootloader investigation
|
||||
- Firmware extraction and analysis
|
||||
- **Documentation**: `docs/phases/PHASE_1_*.md`
|
||||
|
||||
### Phase 2: Bootstrapping
|
||||
- Minimal Linux kernel boot
|
||||
- Basic hardware access
|
||||
- Development environment setup
|
||||
- **Documentation**: `docs/phases/PHASE_2_*.md`
|
||||
|
||||
### Phase 3: Hardware Support
|
||||
- Device drivers development
|
||||
- Input/output systems
|
||||
- Display and audio support
|
||||
- **Documentation**: `docs/phases/PHASE_3_*.md`
|
||||
|
||||
### Phase 4: User Interface
|
||||
- Wayland-based GUI
|
||||
- Keyboard-centric navigation
|
||||
- Core applications
|
||||
- **Documentation**: `docs/phases/PHASE_4_*.md`
|
||||
|
||||
### Phase 5: Telephony Stack
|
||||
- Modem integration
|
||||
- Call/SMS functionality
|
||||
- Network connectivity
|
||||
- **Documentation**: `docs/phases/PHASE_5_*.md`
|
||||
|
||||
### Phase 6: Packaging & Updates
|
||||
- System packaging
|
||||
- Update mechanisms
|
||||
- Security hardening
|
||||
- **Documentation**: `docs/phases/PHASE_6_*.md`
|
||||
|
||||
### Phase 7: Community & SDK
|
||||
- Developer tools
|
||||
- Application ecosystem
|
||||
- Documentation
|
||||
- **Documentation**: `docs/phases/PHASE_7_*.md`
|
||||
|
||||
## 🛠️ Development Workflow
|
||||
|
||||
### Code Organization
|
||||
- **Source code** goes in `src/` directory
|
||||
- **Build artifacts** are placed in `build/` directory
|
||||
- **Scripts** are in `scripts/` directory
|
||||
- **Documentation** is organized in `docs/` subdirectories
|
||||
|
||||
### Testing
|
||||
- **Unit tests** in `tests/` directory
|
||||
- **Hardware testing** with `scripts/hardware-test.sh`
|
||||
- **Emulation testing** with QEMU scripts
|
||||
- **Integration testing** for full system
|
||||
|
||||
### Building Components
|
||||
|
||||
#### Kernel
|
||||
```bash
|
||||
./scripts/build-kernel.sh # Full kernel build
|
||||
./scripts/build-kernel-minimal.sh # Minimal kernel build
|
||||
```
|
||||
|
||||
#### Root Filesystem
|
||||
```bash
|
||||
./scripts/build-rootfs.sh # Build BusyBox rootfs
|
||||
```
|
||||
|
||||
#### Drivers
|
||||
```bash
|
||||
./scripts/build-drivers.sh # Build Q20-specific drivers
|
||||
```
|
||||
|
||||
#### User Interface
|
||||
```bash
|
||||
./scripts/build-ui.sh # Build UI components
|
||||
```
|
||||
|
||||
#### Telephony
|
||||
```bash
|
||||
./scripts/build-telephony.sh # Build telephony stack
|
||||
```
|
||||
|
||||
#### Packaging
|
||||
```bash
|
||||
./scripts/build-packaging.sh # Build system images
|
||||
```
|
||||
|
||||
## 🧪 Testing and Emulation
|
||||
|
||||
### QEMU Emulation
|
||||
```bash
|
||||
./scripts/emulate-simple.sh # Simple QEMU demo
|
||||
./scripts/emulate-bbeos.sh # Full BBeOS emulation
|
||||
./scripts/emulate-terminal.sh # Terminal-based simulation
|
||||
```
|
||||
|
||||
### Hardware Testing
|
||||
```bash
|
||||
./scripts/hardware-test.sh # Hardware component testing
|
||||
```
|
||||
|
||||
## 📚 Documentation
|
||||
|
||||
### Guides
|
||||
- **Emulation Guide**: `docs/guides/EMULATION_GUIDE.md`
|
||||
- **Hardware Testing**: `docs/guides/hardware-testing-guide.md`
|
||||
|
||||
### API Documentation
|
||||
- **UI/UX Design**: `docs/api/UI_UX_DESIGN.md`
|
||||
- **Security Analysis**: `docs/api/SECURITY_ANALYSIS.md`
|
||||
|
||||
### Phase Documentation
|
||||
- **Phase 1**: `docs/phases/PHASE_1_*.md`
|
||||
- **Phase 2**: `docs/phases/PHASE_2_*.md`
|
||||
- **Phase 3**: `docs/phases/PHASE_3_*.md`
|
||||
- **Phase 4**: `docs/phases/PHASE_4_*.md`
|
||||
- **Phase 5**: `docs/phases/PHASE_5_*.md`
|
||||
- **Phase 6**: `docs/phases/PHASE_6_*.md`
|
||||
- **Phase 7**: `docs/phases/PHASE_7_*.md`
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Build Configuration
|
||||
- **Kernel config**: `src/kernel/msm8960-defconfig`
|
||||
- **Device tree**: `vendor/kernel-source/arch/arm/boot/dts/qcom/`
|
||||
|
||||
### Environment Variables
|
||||
- `CROSS_COMPILE`: ARM cross-compilation toolchain
|
||||
- `KERNEL_DIR`: Kernel source directory
|
||||
- `BUILD_DIR`: Build output directory
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### Code Style
|
||||
- Follow Linux kernel coding style for kernel code
|
||||
- Use consistent indentation and naming conventions
|
||||
- Add comments for complex logic
|
||||
- Include error handling
|
||||
|
||||
### Commit Messages
|
||||
- Use descriptive commit messages
|
||||
- Reference issue numbers when applicable
|
||||
- Follow conventional commit format
|
||||
|
||||
### Pull Requests
|
||||
- Create feature branches for new development
|
||||
- Include tests for new functionality
|
||||
- Update documentation as needed
|
||||
- Ensure all tests pass
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
1. **Build failures**: Check toolchain installation
|
||||
2. **Emulation issues**: Verify QEMU installation
|
||||
3. **Hardware problems**: Review device tree configuration
|
||||
|
||||
### Getting Help
|
||||
- Check the documentation in `docs/`
|
||||
- Review phase-specific guides
|
||||
- Test with emulation first
|
||||
- Use hardware testing scripts
|
||||
|
||||
## 📄 License
|
||||
|
||||
BBeOS is open source software licensed under the GPL v3 License. See LICENSE file for details.
|
||||
|
||||
## 🔗 Resources
|
||||
|
||||
- **Repository**: https://gitea.lab48.be/eliott/BBeOS
|
||||
- **Community Website**: `community/website/index.html`
|
||||
- **Hardware Specs**: `hardware/q20-specs.md`
|
||||
- **Research**: `research/` directory
|
||||
|
||||
---
|
||||
|
||||
*This guide is maintained by the BBeOS development team. For questions or contributions, please refer to the project repository.*
|
||||
244
kernel/q20.dts
244
kernel/q20.dts
@ -1,244 +0,0 @@
|
||||
/dts-v1/;
|
||||
|
||||
/ {
|
||||
model = "BlackBerry Classic Q20";
|
||||
compatible = "blackberry,q20", "qcom,msm8960";
|
||||
|
||||
interrupt-parent = <&intc>;
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial0:115200n8";
|
||||
bootargs = "console=ttyMSM0,115200n8 root=/dev/mmcblk0p2 rw rootwait";
|
||||
};
|
||||
|
||||
memory {
|
||||
device_type = "memory";
|
||||
reg = <0x00000000 0x80000000>; // 2GB RAM
|
||||
};
|
||||
|
||||
reserved-memory {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
|
||||
// Reserved for modem
|
||||
modem@0x00000000 {
|
||||
reg = <0x00000000 0x40000000>;
|
||||
no-map;
|
||||
};
|
||||
|
||||
// Reserved for display
|
||||
display@0x40000000 {
|
||||
reg = <0x40000000 0x10000000>;
|
||||
no-map;
|
||||
};
|
||||
};
|
||||
|
||||
cpus {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
|
||||
cpu@0 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <0>;
|
||||
next-level-cache = <&L2>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
|
||||
cpu@1 {
|
||||
device_type = "cpu";
|
||||
compatible = "arm,cortex-a9";
|
||||
reg = <1>;
|
||||
next-level-cache = <&L2>;
|
||||
operating-points-v2 = <&cpu_opp_table>;
|
||||
};
|
||||
};
|
||||
|
||||
cpu_opp_table: opp_table {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp-384000000 {
|
||||
opp-hz = /bits/ 64 <384000000>;
|
||||
opp-microvolt = <1050000>;
|
||||
clock-latency-ns = <256000>;
|
||||
};
|
||||
|
||||
opp-1026000000 {
|
||||
opp-hz = /bits/ 64 <1026000000>;
|
||||
opp-microvolt = <1150000>;
|
||||
clock-latency-ns = <256000>;
|
||||
};
|
||||
|
||||
opp-1500000000 {
|
||||
opp-hz = /bits/ 64 <1500000000>;
|
||||
opp-microvolt = <1250000>;
|
||||
clock-latency-ns = <256000>;
|
||||
};
|
||||
};
|
||||
|
||||
soc {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
compatible = "simple-bus";
|
||||
|
||||
intc: interrupt-controller@2000000 {
|
||||
compatible = "arm,cortex-a9-gic";
|
||||
#interrupt-cells = <3>;
|
||||
#size-cells = <0>;
|
||||
#address-cells = <1>;
|
||||
interrupt-controller;
|
||||
reg = <0x02000000 0x1000>,
|
||||
<0x02002000 0x1000>;
|
||||
};
|
||||
|
||||
L2: l2-cache@2010000 {
|
||||
compatible = "arm,pl310-cache";
|
||||
reg = <0x02010000 0x1000>;
|
||||
arm,data-latency = <3 3 3>;
|
||||
arm,tag-latency = <2 2 2>;
|
||||
cache-unified;
|
||||
cache-level = <2>;
|
||||
};
|
||||
|
||||
// Serial console
|
||||
serial@16440000 {
|
||||
compatible = "qcom,msm-uartdm";
|
||||
reg = <0x16440000 0x1000>;
|
||||
interrupts = <0 154 0>;
|
||||
clocks = <&gcc 108>, <&gcc 109>;
|
||||
clock-names = "core", "iface";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
// Display controller
|
||||
mdp@5100000 {
|
||||
compatible = "qcom,mdp5";
|
||||
reg = <0x05100000 0x90000>;
|
||||
reg-names = "mdp_phys";
|
||||
interrupts = <0 75 0>;
|
||||
clocks = <&gcc 20>, <&gcc 21>;
|
||||
clock-names = "iface", "core";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
// Audio system
|
||||
sound {
|
||||
compatible = "qcom,msm8960-snd-card";
|
||||
qcom,model = "blackberry-q20-snd-card";
|
||||
qcom,audio-routing = "RX_BIAS", "MCLK",
|
||||
"LDO_H", "MCLK";
|
||||
qcom,cdc-mclk-gpios = <&pm8941_gpios 15 0>;
|
||||
};
|
||||
|
||||
// Keyboard controller
|
||||
keyboard@78 {
|
||||
compatible = "blackberry,q20-keyboard";
|
||||
reg = <0x78>;
|
||||
interrupts = <0 123 0>;
|
||||
gpio-controller;
|
||||
#gpio-cells = <2>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
// Trackpad
|
||||
trackpad@5d {
|
||||
compatible = "blackberry,q20-trackpad";
|
||||
reg = <0x5d>;
|
||||
interrupts = <0 124 0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
// Battery management
|
||||
battery {
|
||||
compatible = "blackberry,q20-battery";
|
||||
voltage-min-design-microvolt = <3200000>;
|
||||
voltage-max-design-microvolt = <4200000>;
|
||||
energy-full-design-microwatt-hours = <9500000>;
|
||||
charge-full-design-microamp-hours = <2515000>;
|
||||
};
|
||||
|
||||
// Charger
|
||||
charger {
|
||||
compatible = "blackberry,q20-charger";
|
||||
qcom,fast-charge-current = <1000000>;
|
||||
qcom,fast-charge-voltage = <4200000>;
|
||||
};
|
||||
|
||||
// USB OTG
|
||||
usb@12500000 {
|
||||
compatible = "qcom,ci-hdrc";
|
||||
reg = <0x12500000 0x200>,
|
||||
<0x12500200 0x200>;
|
||||
interrupts = <0 134 0>;
|
||||
status = "okay";
|
||||
dr_mode = "otg";
|
||||
};
|
||||
|
||||
// MMC/SD card
|
||||
mmc@12400000 {
|
||||
compatible = "qcom,msm-sdcc";
|
||||
reg = <0x12400000 0x1000>;
|
||||
interrupts = <0 81 0>;
|
||||
clocks = <&gcc 80>, <&gcc 81>;
|
||||
clock-names = "core", "iface";
|
||||
status = "okay";
|
||||
bus-width = <4>;
|
||||
cap-sd-highspeed;
|
||||
cap-mmc-highspeed;
|
||||
};
|
||||
|
||||
// Wi-Fi
|
||||
wifi@0 {
|
||||
compatible = "qcom,ath6kl";
|
||||
reg = <0x0 0x0>;
|
||||
interrupts = <0 70 0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
// Bluetooth
|
||||
bluetooth@0 {
|
||||
compatible = "qcom,wcn3660";
|
||||
reg = <0x0 0x0>;
|
||||
interrupts = <0 71 0>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
// Display panel
|
||||
panel@0 {
|
||||
compatible = "blackberry,q20-panel";
|
||||
reg = <0>;
|
||||
|
||||
// Panel specifications
|
||||
width-mm = <89>;
|
||||
height-mm = <89>;
|
||||
|
||||
// Display timing
|
||||
display-timings {
|
||||
native-mode = <&timing0>;
|
||||
|
||||
timing0: timing0 {
|
||||
clock-frequency = <72000000>;
|
||||
hactive = <720>;
|
||||
vactive = <720>;
|
||||
hfront-porch = <10>;
|
||||
hsync-len = <10>;
|
||||
hback-porch = <10>;
|
||||
vfront-porch = <10>;
|
||||
vsync-len = <10>;
|
||||
vback-porch = <10>;
|
||||
};
|
||||
};
|
||||
|
||||
// Backlight
|
||||
backlight {
|
||||
compatible = "pwm-backlight";
|
||||
pwms = <&pwm 0 1000000>;
|
||||
brightness-levels = <0 1 2 3 4 5 6 7 8 9 10>;
|
||||
default-brightness-level = <10>;
|
||||
};
|
||||
};
|
||||
};
|
||||
@ -12,7 +12,7 @@ export ARCH=arm
|
||||
export CROSS_COMPILE=arm-linux-gnueabihf-
|
||||
|
||||
# Go to kernel source directory
|
||||
cd kernel-source
|
||||
cd vendor/kernel-source
|
||||
|
||||
# Clean previous build
|
||||
echo "Cleaning previous build..."
|
||||
|
||||
@ -7,8 +7,8 @@ set -e
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
|
||||
KERNEL_DIR="$PROJECT_ROOT/kernel"
|
||||
BUILD_DIR="$PROJECT_ROOT/build"
|
||||
KERNEL_DIR="$PROJECT_ROOT/vendor/kernel-source"
|
||||
BUILD_DIR="$PROJECT_ROOT/build/kernel"
|
||||
TOOLCHAIN_DIR="$PROJECT_ROOT/toolchain"
|
||||
|
||||
# Colors for output
|
||||
|
||||
@ -8,7 +8,7 @@ set -e
|
||||
echo "Building minimal root filesystem for BBeOS..."
|
||||
|
||||
# Configuration
|
||||
ROOTFS_DIR="rootfs"
|
||||
ROOTFS_DIR="build/rootfs"
|
||||
BUSYBOX_VERSION="1.36.1"
|
||||
BUSYBOX_URL="https://busybox.net/downloads/busybox-${BUSYBOX_VERSION}.tar.bz2"
|
||||
BUSYBOX_DIR="busybox-${BUSYBOX_VERSION}"
|
||||
@ -24,16 +24,16 @@ mkdir -p ${ROOTFS_DIR}/{bin,dev,etc,lib,proc,sys,tmp,usr/bin,usr/sbin}
|
||||
|
||||
# Download and build BusyBox
|
||||
echo "Downloading BusyBox ${BUSYBOX_VERSION}..."
|
||||
if [ ! -f "${BUSYBOX_DIR}.tar.bz2" ]; then
|
||||
wget ${BUSYBOX_URL}
|
||||
if [ ! -f "downloads/${BUSYBOX_DIR}.tar.bz2" ]; then
|
||||
wget -O downloads/${BUSYBOX_DIR}.tar.bz2 ${BUSYBOX_URL}
|
||||
fi
|
||||
|
||||
if [ ! -d "${BUSYBOX_DIR}" ]; then
|
||||
tar xf ${BUSYBOX_DIR}.tar.bz2
|
||||
if [ ! -d "downloads/${BUSYBOX_DIR}" ]; then
|
||||
tar xf downloads/${BUSYBOX_DIR}.tar.bz2 -C downloads/
|
||||
fi
|
||||
|
||||
echo "Building BusyBox..."
|
||||
cd ${BUSYBOX_DIR}
|
||||
cd downloads/${BUSYBOX_DIR}
|
||||
|
||||
# Configure BusyBox
|
||||
make defconfig
|
||||
@ -47,8 +47,8 @@ make install
|
||||
|
||||
# Copy BusyBox to rootfs
|
||||
echo "Installing BusyBox to rootfs..."
|
||||
cp busybox ../${ROOTFS_DIR}/bin/
|
||||
cd ..
|
||||
cp busybox ../../${ROOTFS_DIR}/bin/
|
||||
cd ../..
|
||||
|
||||
# Create init script
|
||||
echo "Creating init script..."
|
||||
|
||||
@ -8,10 +8,10 @@ set -e
|
||||
echo "Building BBeOS telephony components..."
|
||||
|
||||
# Configuration
|
||||
TELEPHONY_DIR="telephony"
|
||||
BUILD_DIR="telephony-build"
|
||||
ROOTFS_DIR="rootfs"
|
||||
KERNEL_SRC="kernel-source"
|
||||
TELEPHONY_DIR="src/telephony"
|
||||
BUILD_DIR="build/telephony"
|
||||
ROOTFS_DIR="build/rootfs"
|
||||
KERNEL_SRC="vendor/kernel-source"
|
||||
|
||||
# Set up environment
|
||||
export ARCH=arm
|
||||
|
||||
@ -8,8 +8,8 @@ set -e
|
||||
echo "Building BBeOS UI components..."
|
||||
|
||||
# Configuration
|
||||
UI_DIR="ui"
|
||||
BUILD_DIR="ui-build"
|
||||
UI_DIR="src/ui"
|
||||
BUILD_DIR="build/ui"
|
||||
ROOTFS_DIR="rootfs"
|
||||
|
||||
# Set up environment
|
||||
|
||||
Binary file not shown.
@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("Q20 Home Screen (stub)\n");
|
||||
printf("This is a placeholder for the home screen application\n");
|
||||
printf("Full implementation requires Cairo and Wayland libraries\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
# BBeOS Theme Configuration
|
||||
# BlackBerry Classic Q20 UI Theme
|
||||
|
||||
[colors]
|
||||
background=#1a1a1a
|
||||
foreground=#ffffff
|
||||
accent=#0066cc
|
||||
highlight=#3399ff
|
||||
error=#cc3333
|
||||
success=#33cc33
|
||||
warning=#cc9933
|
||||
|
||||
[fonts]
|
||||
default=Sans 12
|
||||
title=Sans Bold 16
|
||||
status=Sans 10
|
||||
help=Sans 9
|
||||
|
||||
[layout]
|
||||
status_bar_height=40
|
||||
app_grid_size=4
|
||||
app_icon_size=80
|
||||
app_icon_spacing=20
|
||||
@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="720" height="720" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<pattern id="grid" width="20" height="20" patternUnits="userSpaceOnUse">
|
||||
<path d="M 20 0 L 0 0 0 20" fill="none" stroke="#333333" stroke-width="1"/>
|
||||
</pattern>
|
||||
</defs>
|
||||
<rect width="720" height="720" fill="#1a1a1a"/>
|
||||
<rect width="720" height="720" fill="url(#grid)"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 408 B |
Binary file not shown.
@ -1,9 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
printf("Q20 Compositor (stub)\n");
|
||||
printf("This is a placeholder for the Wayland compositor\n");
|
||||
printf("Full implementation requires wlroots library\n");
|
||||
return 0;
|
||||
}
|
||||
71
ui/Makefile
71
ui/Makefile
@ -1,71 +0,0 @@
|
||||
# BBeOS UI Build System
|
||||
# Builds UI components for BlackBerry Classic Q20
|
||||
|
||||
# Configuration
|
||||
CC = arm-linux-gnueabihf-gcc
|
||||
CFLAGS = -Wall -Wextra -O2 -g
|
||||
LDFLAGS =
|
||||
|
||||
# Libraries
|
||||
WAYLAND_LIBS = -lwayland-client -lwayland-server
|
||||
WLROOTS_LIBS = -lwlr -lwlr-util
|
||||
CAIRO_LIBS = -lcairo -lpango-1.0 -lpangocairo-1.0
|
||||
XKB_LIBS = -lxkbcommon
|
||||
MATH_LIBS = -lm
|
||||
|
||||
# Directories
|
||||
COMPOSITOR_DIR = compositor
|
||||
APPLICATIONS_DIR = applications
|
||||
FRAMEWORK_DIR = framework
|
||||
ASSETS_DIR = assets
|
||||
|
||||
# Targets
|
||||
all: compositor applications
|
||||
|
||||
compositor: $(COMPOSITOR_DIR)/q20-compositor
|
||||
|
||||
applications: $(APPLICATIONS_DIR)/home-screen
|
||||
|
||||
# Compositor
|
||||
$(COMPOSITOR_DIR)/q20-compositor: $(COMPOSITOR_DIR)/q20-compositor.c
|
||||
$(CC) $(CFLAGS) -o $@ $< $(WAYLAND_LIBS) $(WLROOTS_LIBS) $(XKB_LIBS) $(MATH_LIBS)
|
||||
|
||||
# Applications
|
||||
$(APPLICATIONS_DIR)/home-screen: $(APPLICATIONS_DIR)/home-screen.c
|
||||
$(CC) $(CFLAGS) -o $@ $< $(WAYLAND_LIBS) $(CAIRO_LIBS) $(MATH_LIBS)
|
||||
|
||||
# Framework (placeholder for future components)
|
||||
framework:
|
||||
@echo "Building UI framework components..."
|
||||
# TODO: Add framework components
|
||||
|
||||
# Assets
|
||||
assets:
|
||||
@echo "Processing UI assets..."
|
||||
# TODO: Add asset processing
|
||||
|
||||
# Installation
|
||||
install: all
|
||||
@echo "Installing UI components..."
|
||||
mkdir -p $(DESTDIR)/usr/bin
|
||||
mkdir -p $(DESTDIR)/usr/share/bbeos/ui
|
||||
cp $(COMPOSITOR_DIR)/q20-compositor $(DESTDIR)/usr/bin/
|
||||
cp $(APPLICATIONS_DIR)/home-screen $(DESTDIR)/usr/bin/
|
||||
cp -r $(ASSETS_DIR)/* $(DESTDIR)/usr/share/bbeos/ui/ 2>/dev/null || true
|
||||
|
||||
# Clean
|
||||
clean:
|
||||
rm -f $(COMPOSITOR_DIR)/q20-compositor
|
||||
rm -f $(APPLICATIONS_DIR)/home-screen
|
||||
rm -f $(FRAMEWORK_DIR)/*.o
|
||||
rm -f $(FRAMEWORK_DIR)/*.a
|
||||
|
||||
# Development targets
|
||||
dev: CFLAGS += -DDEBUG -g3
|
||||
dev: all
|
||||
|
||||
# Release targets
|
||||
release: CFLAGS += -DNDEBUG -O3
|
||||
release: all
|
||||
|
||||
.PHONY: all compositor applications framework assets install clean dev release
|
||||
@ -1,266 +0,0 @@
|
||||
/*
|
||||
* Q20 Home Screen Application
|
||||
* BlackBerry Classic Q20 Main Interface
|
||||
*
|
||||
* A keyboard-optimized home screen with app launcher,
|
||||
* status bar, and navigation system.
|
||||
*/
|
||||
|
||||
#include <wayland-client.h>
|
||||
#include <cairo/cairo.h>
|
||||
#include <pango/pango.h>
|
||||
#include <pango/pangocairo.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
|
||||
#define Q20_WIDTH 720
|
||||
#define Q20_HEIGHT 720
|
||||
#define STATUS_BAR_HEIGHT 40
|
||||
#define APP_GRID_SIZE 4
|
||||
#define APP_ICON_SIZE 80
|
||||
#define APP_ICON_SPACING 20
|
||||
|
||||
struct q20_home_screen {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
struct wl_surface *surface;
|
||||
struct wl_shell *shell;
|
||||
struct wl_shell_surface *shell_surface;
|
||||
|
||||
cairo_surface_t *cairo_surface;
|
||||
cairo_t *cairo;
|
||||
|
||||
int selected_app;
|
||||
int app_count;
|
||||
char *app_names[16];
|
||||
char *app_commands[16];
|
||||
|
||||
time_t last_update;
|
||||
};
|
||||
|
||||
static void draw_status_bar(struct q20_home_screen *home) {
|
||||
cairo_t *cr = home->cairo;
|
||||
char time_str[64];
|
||||
time_t now = time(NULL);
|
||||
struct tm *tm_info = localtime(&now);
|
||||
|
||||
strftime(time_str, sizeof(time_str), "%H:%M", tm_info);
|
||||
|
||||
// Draw status bar background
|
||||
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
|
||||
cairo_rectangle(cr, 0, 0, Q20_WIDTH, STATUS_BAR_HEIGHT);
|
||||
cairo_fill(cr);
|
||||
|
||||
// Draw time
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD);
|
||||
cairo_set_font_size(cr, 16);
|
||||
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents(cr, time_str, &extents);
|
||||
cairo_move_to(cr, Q20_WIDTH - extents.width - 10, STATUS_BAR_HEIGHT / 2 + extents.height / 2);
|
||||
cairo_show_text(cr, time_str);
|
||||
|
||||
// Draw "BBeOS" title
|
||||
cairo_move_to(cr, 10, STATUS_BAR_HEIGHT / 2 + extents.height / 2);
|
||||
cairo_show_text(cr, "BBeOS");
|
||||
}
|
||||
|
||||
static void draw_app_grid(struct q20_home_screen *home) {
|
||||
cairo_t *cr = home->cairo;
|
||||
int start_y = STATUS_BAR_HEIGHT + 20;
|
||||
int start_x = (Q20_WIDTH - (APP_GRID_SIZE * APP_ICON_SIZE + (APP_GRID_SIZE - 1) * APP_ICON_SPACING)) / 2;
|
||||
|
||||
for (int i = 0; i < home->app_count; i++) {
|
||||
int row = i / APP_GRID_SIZE;
|
||||
int col = i % APP_GRID_SIZE;
|
||||
int x = start_x + col * (APP_ICON_SIZE + APP_ICON_SPACING);
|
||||
int y = start_y + row * (APP_ICON_SIZE + APP_ICON_SPACING + 30);
|
||||
|
||||
// Draw selection highlight
|
||||
if (i == home->selected_app) {
|
||||
cairo_set_source_rgb(cr, 0.2, 0.6, 1.0);
|
||||
cairo_rectangle(cr, x - 5, y - 5, APP_ICON_SIZE + 10, APP_ICON_SIZE + 35);
|
||||
cairo_fill(cr);
|
||||
}
|
||||
|
||||
// Draw app icon background
|
||||
cairo_set_source_rgb(cr, 0.3, 0.3, 0.3);
|
||||
cairo_rectangle(cr, x, y, APP_ICON_SIZE, APP_ICON_SIZE);
|
||||
cairo_fill(cr);
|
||||
|
||||
// Draw app icon border
|
||||
cairo_set_source_rgb(cr, 0.5, 0.5, 0.5);
|
||||
cairo_set_line_width(cr, 2);
|
||||
cairo_rectangle(cr, x, y, APP_ICON_SIZE, APP_ICON_SIZE);
|
||||
cairo_stroke(cr);
|
||||
|
||||
// Draw app name
|
||||
cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
|
||||
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(cr, 12);
|
||||
|
||||
cairo_text_extents_t extents;
|
||||
cairo_text_extents(cr, home->app_names[i], &extents);
|
||||
cairo_move_to(cr, x + (APP_ICON_SIZE - extents.width) / 2, y + APP_ICON_SIZE + 15);
|
||||
cairo_show_text(cr, home->app_names[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void draw_help_text(struct q20_home_screen *home) {
|
||||
cairo_t *cr = home->cairo;
|
||||
|
||||
cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
|
||||
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
|
||||
cairo_set_font_size(cr, 10);
|
||||
|
||||
const char *help_text[] = {
|
||||
"Arrow Keys: Navigate",
|
||||
"Enter: Launch App",
|
||||
"F1: Settings",
|
||||
"F2: Terminal",
|
||||
"Esc: Exit"
|
||||
};
|
||||
|
||||
int y = Q20_HEIGHT - 80;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
cairo_move_to(cr, 10, y + i * 12);
|
||||
cairo_show_text(cr, help_text[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void redraw(struct q20_home_screen *home) {
|
||||
cairo_t *cr = home->cairo;
|
||||
|
||||
// Clear background
|
||||
cairo_set_source_rgb(cr, 0.15, 0.15, 0.15);
|
||||
cairo_paint(cr);
|
||||
|
||||
// Draw components
|
||||
draw_status_bar(home);
|
||||
draw_app_grid(home);
|
||||
draw_help_text(home);
|
||||
|
||||
// Commit the surface
|
||||
wl_surface_damage(home->surface, 0, 0, Q20_WIDTH, Q20_HEIGHT);
|
||||
wl_surface_commit(home->surface);
|
||||
}
|
||||
|
||||
static void handle_keyboard_input(struct q20_home_screen *home, uint32_t key) {
|
||||
switch (key) {
|
||||
case 111: // Up arrow
|
||||
if (home->selected_app >= APP_GRID_SIZE) {
|
||||
home->selected_app -= APP_GRID_SIZE;
|
||||
}
|
||||
break;
|
||||
case 116: // Down arrow
|
||||
if (home->selected_app + APP_GRID_SIZE < home->app_count) {
|
||||
home->selected_app += APP_GRID_SIZE;
|
||||
}
|
||||
break;
|
||||
case 113: // Left arrow
|
||||
if (home->selected_app > 0) {
|
||||
home->selected_app--;
|
||||
}
|
||||
break;
|
||||
case 114: // Right arrow
|
||||
if (home->selected_app < home->app_count - 1) {
|
||||
home->selected_app++;
|
||||
}
|
||||
break;
|
||||
case 36: // Enter
|
||||
if (home->selected_app < home->app_count) {
|
||||
// Launch the selected app
|
||||
printf("Launching: %s\n", home->app_commands[home->selected_app]);
|
||||
// TODO: Actually launch the app
|
||||
}
|
||||
break;
|
||||
case 9: // Escape
|
||||
printf("Exiting home screen\n");
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
redraw(home);
|
||||
}
|
||||
|
||||
static void init_apps(struct q20_home_screen *home) {
|
||||
home->app_count = 0;
|
||||
|
||||
// Add default apps
|
||||
home->app_names[home->app_count] = "Terminal";
|
||||
home->app_commands[home->app_count] = "weston-terminal";
|
||||
home->app_count++;
|
||||
|
||||
home->app_names[home->app_count] = "Settings";
|
||||
home->app_commands[home->app_count] = "weston-settings";
|
||||
home->app_count++;
|
||||
|
||||
home->app_names[home->app_count] = "File Manager";
|
||||
home->app_commands[home->app_count] = "weston-file-manager";
|
||||
home->app_count++;
|
||||
|
||||
home->app_names[home->app_count] = "Calculator";
|
||||
home->app_commands[home->app_count] = "weston-calculator";
|
||||
home->app_count++;
|
||||
|
||||
home->app_names[home->app_count] = "Notes";
|
||||
home->app_commands[home->app_count] = "weston-notes";
|
||||
home->app_count++;
|
||||
|
||||
home->app_names[home->app_count] = "Calendar";
|
||||
home->app_commands[home->app_count] = "weston-calendar";
|
||||
home->app_count++;
|
||||
|
||||
home->selected_app = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct q20_home_screen home = {0};
|
||||
|
||||
// Connect to Wayland display
|
||||
home.display = wl_display_connect(NULL);
|
||||
if (!home.display) {
|
||||
fprintf(stderr, "Failed to connect to Wayland display\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Get registry and bind to interfaces
|
||||
struct wl_registry *registry = wl_display_get_registry(home.display);
|
||||
|
||||
// TODO: Add proper registry listener to bind to compositor, shell, etc.
|
||||
// For now, we'll create a simple surface
|
||||
|
||||
// Create Cairo surface
|
||||
home.cairo_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, Q20_WIDTH, Q20_HEIGHT);
|
||||
home.cairo = cairo_create(home.cairo_surface);
|
||||
|
||||
// Initialize apps
|
||||
init_apps(&home);
|
||||
|
||||
// Initial draw
|
||||
redraw(&home);
|
||||
|
||||
printf("Q20 Home Screen started\n");
|
||||
printf("Use arrow keys to navigate, Enter to launch apps\n");
|
||||
|
||||
// Main event loop
|
||||
while (1) {
|
||||
wl_display_dispatch(home.display);
|
||||
|
||||
// Handle keyboard input (simplified for now)
|
||||
// TODO: Add proper Wayland keyboard input handling
|
||||
|
||||
usleep(100000); // 100ms
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
cairo_destroy(home.cairo);
|
||||
cairo_surface_destroy(home.cairo_surface);
|
||||
wl_display_disconnect(home.display);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,361 +0,0 @@
|
||||
/*
|
||||
* Q20 Wayland Compositor
|
||||
* BlackBerry Classic Q20 Display Server
|
||||
*
|
||||
* A lightweight Wayland compositor optimized for the Q20's
|
||||
* 720x720 square display and keyboard navigation.
|
||||
*/
|
||||
|
||||
#include <wayland-server.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_data_device.h>
|
||||
#include <wlr/types/wlr_input_device.h>
|
||||
#include <wlr/types/wlr_keyboard.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xkbcommon/xkbcommon.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
struct q20_server {
|
||||
struct wl_display *wl_display;
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_compositor *compositor;
|
||||
struct wlr_seat *seat;
|
||||
struct wlr_output *output;
|
||||
struct wlr_xdg_shell *xdg_shell;
|
||||
|
||||
struct wl_listener new_output;
|
||||
struct wl_listener new_input;
|
||||
struct wl_listener new_xdg_surface;
|
||||
|
||||
struct wl_list views;
|
||||
struct wl_list keyboards;
|
||||
|
||||
struct wlr_view *focused_view;
|
||||
struct wlr_keyboard *focused_keyboard;
|
||||
};
|
||||
|
||||
struct q20_view {
|
||||
struct wl_list link;
|
||||
struct q20_server *server;
|
||||
struct wlr_xdg_surface *xdg_surface;
|
||||
struct wl_listener map;
|
||||
struct wl_listener unmap;
|
||||
struct wl_listener destroy;
|
||||
struct wl_listener request_move;
|
||||
struct wl_listener request_resize;
|
||||
struct wl_listener request_maximize;
|
||||
struct wl_listener request_fullscreen;
|
||||
|
||||
int x, y;
|
||||
bool maximized;
|
||||
bool fullscreen;
|
||||
};
|
||||
|
||||
struct q20_keyboard {
|
||||
struct wl_list link;
|
||||
struct q20_server *server;
|
||||
struct wlr_input_device *device;
|
||||
struct wl_listener key;
|
||||
struct wl_listener modifiers;
|
||||
struct wl_listener destroy;
|
||||
|
||||
struct xkb_state *xkb_state;
|
||||
xkb_keycode_t repeat_keycode;
|
||||
uint32_t repeat_time;
|
||||
struct wl_event_source *repeat_source;
|
||||
};
|
||||
|
||||
static void focus_view(struct q20_server *server, struct q20_view *view) {
|
||||
if (server->focused_view == view) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (server->focused_view) {
|
||||
struct wlr_xdg_surface *previous_surface = server->focused_view->xdg_surface;
|
||||
wlr_xdg_toplevel_set_activated(previous_surface, false);
|
||||
}
|
||||
|
||||
server->focused_view = view;
|
||||
|
||||
if (view) {
|
||||
wlr_xdg_toplevel_set_activated(view->xdg_surface, true);
|
||||
wlr_seat_keyboard_notify_enter(server->seat, view->xdg_surface->surface,
|
||||
NULL, 0, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void keyboard_key_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_keyboard *keyboard = wl_container_of(listener, keyboard, key);
|
||||
struct q20_server *server = keyboard->server;
|
||||
struct wlr_event_keyboard_key *event = data;
|
||||
struct wlr_seat *seat = server->seat;
|
||||
|
||||
// Get the keycode and translate it to a keysym
|
||||
xkb_keycode_t keycode = event->keycode + 8;
|
||||
xkb_keysym_t sym = xkb_state_key_get_one_sym(keyboard->xkb_state, keycode);
|
||||
|
||||
// Handle Q20-specific key combinations
|
||||
if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
switch (sym) {
|
||||
case XKB_KEY_Escape:
|
||||
// Exit compositor
|
||||
wl_display_terminate(server->wl_display);
|
||||
break;
|
||||
case XKB_KEY_F1:
|
||||
// Switch to next view
|
||||
// TODO: Implement view switching
|
||||
break;
|
||||
case XKB_KEY_F2:
|
||||
// Toggle maximize
|
||||
if (server->focused_view) {
|
||||
server->focused_view->maximized = !server->focused_view->maximized;
|
||||
if (server->focused_view->maximized) {
|
||||
wlr_xdg_toplevel_set_maximized(server->focused_view->xdg_surface, true);
|
||||
} else {
|
||||
wlr_xdg_toplevel_set_maximized(server->focused_view->xdg_surface, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case XKB_KEY_F3:
|
||||
// Toggle fullscreen
|
||||
if (server->focused_view) {
|
||||
server->focused_view->fullscreen = !server->focused_view->fullscreen;
|
||||
if (server->focused_view->fullscreen) {
|
||||
wlr_xdg_toplevel_set_fullscreen(server->focused_view->xdg_surface, true);
|
||||
} else {
|
||||
wlr_xdg_toplevel_set_fullscreen(server->focused_view->xdg_surface, false);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_seat_keyboard_notify_key(seat, event->time_msec, event->keycode, event->state);
|
||||
}
|
||||
|
||||
static void keyboard_modifiers_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_keyboard *keyboard = wl_container_of(listener, keyboard, modifiers);
|
||||
struct q20_server *server = keyboard->server;
|
||||
|
||||
wlr_seat_keyboard_notify_modifiers(server->seat, &keyboard->device->keyboard->modifiers);
|
||||
}
|
||||
|
||||
static void keyboard_destroy_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_keyboard *keyboard = wl_container_of(listener, keyboard, destroy);
|
||||
|
||||
wl_list_remove(&keyboard->link);
|
||||
free(keyboard);
|
||||
}
|
||||
|
||||
static void server_new_keyboard(struct q20_server *server, struct wlr_input_device *device) {
|
||||
struct q20_keyboard *keyboard = calloc(1, sizeof(struct q20_keyboard));
|
||||
keyboard->server = server;
|
||||
keyboard->device = device;
|
||||
|
||||
// Get the keymap
|
||||
struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
|
||||
struct xkb_keymap *keymap = xkb_keymap_new_from_names(context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS);
|
||||
|
||||
keyboard->xkb_state = xkb_state_new(keymap);
|
||||
xkb_keymap_unref(keymap);
|
||||
xkb_context_unref(context);
|
||||
|
||||
wlr_keyboard_set_keymap(device->keyboard, keymap);
|
||||
wlr_keyboard_set_repeat_info(device->keyboard, 25, 600);
|
||||
|
||||
keyboard->key.notify = keyboard_key_notify;
|
||||
wl_signal_add(&device->keyboard->events.key, &keyboard->key);
|
||||
|
||||
keyboard->modifiers.notify = keyboard_modifiers_notify;
|
||||
wl_signal_add(&device->keyboard->events.modifiers, &keyboard->modifiers);
|
||||
|
||||
keyboard->destroy.notify = keyboard_destroy_notify;
|
||||
wl_signal_add(&device->events.destroy, &keyboard->destroy);
|
||||
|
||||
wl_list_insert(&server->keyboards, &keyboard->link);
|
||||
|
||||
// Set this keyboard as the current one
|
||||
wlr_seat_set_keyboard(server->seat, device);
|
||||
}
|
||||
|
||||
static void server_new_input_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_server *server = wl_container_of(listener, server, new_input);
|
||||
struct wlr_input_device *device = data;
|
||||
|
||||
switch (device->type) {
|
||||
case WLR_INPUT_DEVICE_KEYBOARD:
|
||||
server_new_keyboard(server, device);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void view_map_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_view *view = wl_container_of(listener, view, map);
|
||||
struct q20_server *server = view->server;
|
||||
|
||||
// Center the view on the 720x720 display
|
||||
view->x = (720 - view->xdg_surface->surface->current.width) / 2;
|
||||
view->y = (720 - view->xdg_surface->surface->current.height) / 2;
|
||||
|
||||
focus_view(server, view);
|
||||
}
|
||||
|
||||
static void view_unmap_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_view *view = wl_container_of(listener, view, unmap);
|
||||
struct q20_server *server = view->server;
|
||||
|
||||
if (server->focused_view == view) {
|
||||
focus_view(server, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void view_destroy_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_view *view = wl_container_of(listener, view, destroy);
|
||||
|
||||
wl_list_remove(&view->link);
|
||||
free(view);
|
||||
}
|
||||
|
||||
static void server_new_xdg_surface_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_server *server = wl_container_of(listener, server, new_xdg_surface);
|
||||
struct wlr_xdg_surface *xdg_surface = data;
|
||||
|
||||
if (xdg_surface->role != WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct q20_view *view = calloc(1, sizeof(struct q20_view));
|
||||
view->server = server;
|
||||
view->xdg_surface = xdg_surface;
|
||||
|
||||
view->map.notify = view_map_notify;
|
||||
wl_signal_add(&xdg_surface->events.map, &view->map);
|
||||
|
||||
view->unmap.notify = view_unmap_notify;
|
||||
wl_signal_add(&xdg_surface->events.unmap, &view->unmap);
|
||||
|
||||
view->destroy.notify = view_destroy_notify;
|
||||
wl_signal_add(&xdg_surface->events.destroy, &view->destroy);
|
||||
|
||||
wl_list_insert(&server->views, &view->link);
|
||||
}
|
||||
|
||||
static void output_frame_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_server *server = wl_container_of(listener, server, output_frame);
|
||||
struct wlr_output *output = data;
|
||||
struct wlr_renderer *renderer = server->renderer;
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
wlr_output_make_current(output, NULL);
|
||||
wlr_renderer_begin(renderer, output->width, output->height);
|
||||
|
||||
float color[4] = {0.1f, 0.1f, 0.1f, 1.0f};
|
||||
wlr_renderer_clear(renderer, color);
|
||||
|
||||
// Render all views
|
||||
struct q20_view *view;
|
||||
wl_list_for_each_reverse(view, &server->views, link) {
|
||||
if (!view->xdg_surface->mapped) {
|
||||
continue;
|
||||
}
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = view->x,
|
||||
.y = view->y,
|
||||
.width = view->xdg_surface->surface->current.width,
|
||||
.height = view->xdg_surface->surface->current.height,
|
||||
};
|
||||
|
||||
wlr_renderer_scissor(renderer, &box);
|
||||
wlr_render_texture(renderer, view->xdg_surface->surface->texture, output->transform_matrix, box.x, box.y, 1.0f);
|
||||
}
|
||||
|
||||
wlr_renderer_scissor(renderer, NULL);
|
||||
wlr_renderer_end(renderer);
|
||||
|
||||
wlr_output_swap_buffers(output, NULL, NULL);
|
||||
}
|
||||
|
||||
static void server_new_output_notify(struct wl_listener *listener, void *data) {
|
||||
struct q20_server *server = wl_container_of(listener, server, new_output);
|
||||
struct wlr_output *output = data;
|
||||
|
||||
if (!wl_list_empty(&output->modes)) {
|
||||
struct wlr_output_mode *mode = wl_container_of(output->modes.prev, mode, link);
|
||||
wlr_output_set_mode(output, mode);
|
||||
}
|
||||
|
||||
// Configure for Q20's 720x720 display
|
||||
wlr_output_set_custom_mode(output, 720, 720, 60000);
|
||||
|
||||
wlr_output_create_global(output);
|
||||
|
||||
server->output = output;
|
||||
|
||||
output->frame.notify = output_frame_notify;
|
||||
wl_signal_add(&output->events.frame, &output->frame);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
wlr_log_init(WLR_DEBUG, NULL);
|
||||
|
||||
struct q20_server server = {0};
|
||||
|
||||
server.wl_display = wl_display_create();
|
||||
server.backend = wlr_backend_autocreate(server.wl_display);
|
||||
server.renderer = wlr_renderer_autocreate(server.backend);
|
||||
wlr_renderer_init_wl_display(server.renderer, server.wl_display);
|
||||
|
||||
server.compositor = wlr_compositor_create(server.wl_display, server.renderer);
|
||||
wlr_export_dmabuf_manager_v1_create(server.wl_display);
|
||||
wlr_screencopy_manager_v1_create(server.wl_display);
|
||||
wlr_data_device_manager_create(server.wl_display);
|
||||
|
||||
server.seat = wlr_seat_create(server.wl_display, "seat0");
|
||||
|
||||
server.xdg_shell = wlr_xdg_shell_create(server.wl_display);
|
||||
server.new_xdg_surface.notify = server_new_xdg_surface_notify;
|
||||
wl_signal_add(&server.xdg_shell->events.new_surface, &server.new_xdg_surface);
|
||||
|
||||
wl_list_init(&server.views);
|
||||
wl_list_init(&server.keyboards);
|
||||
|
||||
server.new_output.notify = server_new_output_notify;
|
||||
wl_signal_add(&server.backend->events.new_output, &server.new_output);
|
||||
|
||||
server.new_input.notify = server_new_input_notify;
|
||||
wl_signal_add(&server.backend->events.new_input, &server.new_input);
|
||||
|
||||
const char *socket = wl_display_add_socket_auto(server.wl_display);
|
||||
if (!socket) {
|
||||
wlr_backend_destroy(server.backend);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!wlr_backend_start(server.backend)) {
|
||||
wlr_backend_destroy(server.backend);
|
||||
wl_display_destroy(server.wl_display);
|
||||
return 1;
|
||||
}
|
||||
|
||||
setenv("WAYLAND_DISPLAY", socket, true);
|
||||
wlr_log(WLR_INFO, "Running Q20 compositor on WAYLAND_DISPLAY=%s", socket);
|
||||
|
||||
wl_display_run(server.wl_display);
|
||||
|
||||
wl_display_destroy(server.wl_display);
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user