diff --git a/OSDP-Bench.sln.DotSettings b/OSDP-Bench.sln.DotSettings
index a7fc0a9..ec3bac6 100644
--- a/OSDP-Bench.sln.DotSettings
+++ b/OSDP-Bench.sln.DotSettings
@@ -1,4 +1,5 @@
CRC
+ .XX
True
True
\ No newline at end of file
diff --git a/README.md b/README.md
index 50852ee..cab7b5a 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,7 @@
A professional tool for configuring and troubleshooting OSDP devices.
[](https://dotnet.microsoft.com/)
-[](LICENSE)
-[](https://docs.microsoft.com/en-us/windows/)
+[](LICENSE)
## About
@@ -21,6 +20,15 @@ Core functionality is under an open source license to help increase the adoption
- **Multi-language Support** - Available in multiple languages
- **Cross-platform** - Built on .NET 8.0 for modern compatibility
+## Get OSDP Bench
+
+### Download the App
+
+OSDP Bench is available for purchase on multiple platforms:
+
+[](ms-windows-store://pdp/?productid=9N3W7QR3R5S7&cid=&mode=mini)
+[](https://play.google.com/store/apps/details?id=com.z_bitco.com.osdpbenchmobile)
+
## Getting Started
### Prerequisites
@@ -29,7 +37,7 @@ Core functionality is under an open source license to help increase the adoption
- Windows 10/11 (for WinUI version)
- Serial port access for device communication
-### Installation
+### Building from Source
1. Clone the repository:
```bash
@@ -84,9 +92,27 @@ For documentation contributions:
3. Update this README to include the new file
4. Follow the existing documentation style and structure
+### Release Process
+
+To create a new release:
+
+1. Ensure you're on the `develop` branch with all changes committed
+2. Run the release script:
+ ```powershell
+ ./ci/release.ps1
+ ```
+3. The script will:
+ - Verify no uncommitted changes exist
+ - Check that develop is ahead of main
+ - Display changes to be released
+ - Merge develop into main (with confirmation)
+ - Push to trigger automated CI/CD pipeline
+
+The CI pipeline will automatically handle version bumping and release creation.
+
## License
-This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
+This project is licensed under the Eclipse Public License 2.0 - see the [LICENSE](LICENSE) file for details.
## Contact
diff --git a/ci/azure-pipeline-resource-check.yml b/ci/azure-pipeline-resource-check.yml
new file mode 100644
index 0000000..f5a3063
--- /dev/null
+++ b/ci/azure-pipeline-resource-check.yml
@@ -0,0 +1,65 @@
+# Azure DevOps Pipeline for Resource Usage Analysis
+# This pipeline runs the PowerShell resource usage checker
+
+trigger:
+ branches:
+ include:
+ - main
+ - develop
+ paths:
+ include:
+ - 'src/Core/Resources/*'
+ - 'src/**/*.cs'
+ - 'src/**/*.xaml'
+
+pr:
+ branches:
+ include:
+ - main
+ - develop
+ paths:
+ include:
+ - 'src/Core/Resources/*'
+ - 'src/**/*.cs'
+ - 'src/**/*.xaml'
+
+pool:
+ vmImage: 'windows-latest'
+
+variables:
+ buildConfiguration: 'Release'
+
+steps:
+- checkout: self
+ displayName: 'Checkout source code'
+
+- task: PowerShell@2
+ displayName: 'Check Resource Usage'
+ inputs:
+ filePath: 'check_resource_usage.ps1'
+ arguments: '-Verbose'
+ pwsh: true
+ workingDirectory: '$(Build.SourcesDirectory)'
+ continueOnError: true
+
+- task: PowerShell@2
+ displayName: 'Resource Check Summary'
+ inputs:
+ targetType: 'inline'
+ script: |
+ Write-Host "##[section]Resource Usage Analysis Complete"
+ Write-Host "##[command]Review the output above for any unused resources or missing definitions"
+ Write-Host "##[command]Consider cleaning up unused resources to maintain code quality"
+ pwsh: true
+ condition: always()
+
+# Optional: Fail the build if critical issues are found
+# Uncomment the following task if you want the pipeline to fail on resource issues
+# - task: PowerShell@2
+# displayName: 'Fail on Critical Resource Issues'
+# inputs:
+# filePath: 'check_resource_usage.ps1'
+# arguments: '-Verbose'
+# pwsh: true
+# workingDirectory: '$(Build.SourcesDirectory)'
+# condition: always()
\ No newline at end of file
diff --git a/ci/check_resource_usage.ps1 b/ci/check_resource_usage.ps1
new file mode 100644
index 0000000..da5a27b
--- /dev/null
+++ b/ci/check_resource_usage.ps1
@@ -0,0 +1,239 @@
+# OSDP-Bench Resource Usage Checker (With Progress Indicator)
+
+Write-Host "=== OSDP-Bench Resource Usage Analysis ===" -ForegroundColor Cyan
+Write-Host
+
+$ResourceFile = "src/Core/Resources/Resources.resx"
+
+# Phase 1: Extract resource keys
+Write-Host "Phase 1: Extracting resource keys from Resources.resx..." -ForegroundColor Yellow
+
+if (-not (Test-Path $ResourceFile)) {
+ Write-Host "Error: Resources.resx not found at $ResourceFile" -ForegroundColor Red
+ exit 1
+}
+
+[xml]$resourceXml = Get-Content $ResourceFile
+$resourceKeys = $resourceXml.root.data | Where-Object { $_.name } | Select-Object -ExpandProperty name | Sort-Object
+
+Write-Host "Found $($resourceKeys.Count) resource keys" -ForegroundColor Green
+Write-Host
+
+# Phase 2: Check usage with progress
+Write-Host "Phase 2: Checking usage of each resource key..." -ForegroundColor Yellow
+
+$usedKeys = @()
+$unusedKeys = @()
+$total = $resourceKeys.Count
+$current = 0
+
+# Check if ripgrep is available for faster processing
+$rgAvailable = $null -ne (Get-Command "rg" -ErrorAction SilentlyContinue)
+if ($rgAvailable) {
+ Write-Host "Using ripgrep for fast searching..." -ForegroundColor Gray
+} else {
+ Write-Host "Using PowerShell Select-String (slower fallback)..." -ForegroundColor Gray
+}
+
+foreach ($key in $resourceKeys) {
+ $current++
+ $percentComplete = [math]::Round(($current / $total) * 100, 1)
+
+ # Update progress bar
+ Write-Progress -Activity "Checking Resource Usage" -Status "Processing $key ($current of $total)" -PercentComplete $percentComplete
+
+ $found = $false
+
+ if ($rgAvailable) {
+ # Use ripgrep patterns - simplified for speed
+ try {
+ & rg -q $key "src" "test" --glob="*.cs" --glob="*.xaml" 2>$null
+ if ($LASTEXITCODE -eq 0) {
+ $found = $true
+ }
+ }
+ catch {
+ # Continue if rg fails
+ }
+ }
+ else {
+ # Fallback to Select-String
+ $files = Get-ChildItem -Path "src", "test" -Recurse -Include "*.cs", "*.xaml" -ErrorAction SilentlyContinue
+
+ if ($files | Select-String -Pattern $key -Quiet) {
+ $found = $true
+ }
+ }
+
+ if ($found) {
+ $usedKeys += $key
+ Write-Host "✓ $key" -ForegroundColor Green
+ }
+ else {
+ $unusedKeys += $key
+ Write-Host "✗ $key" -ForegroundColor Red
+ }
+}
+
+# Clear progress bar
+Write-Progress -Activity "Checking Resource Usage" -Completed
+
+Write-Host
+Write-Host "=== SUMMARY ===" -ForegroundColor Cyan
+Write-Host "Used resource keys: $($usedKeys.Count)" -ForegroundColor Green
+Write-Host "Unused resource keys: $($unusedKeys.Count)" -ForegroundColor Red
+
+if ($unusedKeys.Count -gt 0) {
+ Write-Host
+ Write-Host "=== UNUSED RESOURCE KEYS ===" -ForegroundColor Yellow
+
+ foreach ($key in $unusedKeys) {
+ $dataNode = $resourceXml.root.data | Where-Object { $_.name -eq $key }
+ $value = if ($dataNode.value) { $dataNode.value } else { "" }
+ $comment = if ($dataNode.comment) { $dataNode.comment } else { "" }
+
+ Write-Host $key -ForegroundColor Red
+ Write-Host " Value: `"$value`""
+ if ($comment) {
+ Write-Host " Comment: $comment"
+ }
+ Write-Host
+ }
+
+ Write-Host "Consider removing these unused resource strings to clean up the codebase." -ForegroundColor Yellow
+}
+else {
+ Write-Host "All resource strings are being used! 🎉" -ForegroundColor Green
+}
+
+Write-Host
+
+# Phase 3: Check for missing resource definitions
+Write-Host "Phase 3: Checking for resource lookups without definitions..." -ForegroundColor Yellow
+
+$missingKeys = @()
+$missingDetails = @()
+
+# Get all source files
+$allFiles = Get-ChildItem -Path "src", "test" -Recurse -Include "*.cs", "*.xaml" -ErrorAction SilentlyContinue
+
+Write-Host "Found $($allFiles.Count) source files to scan..." -ForegroundColor Gray
+Write-Progress -Activity "Phase 3: Scanning for Missing Definitions" -Status "Initializing scan..." -PercentComplete 0
+
+$fileCount = 0
+$totalFiles = $allFiles.Count
+
+foreach ($file in $allFiles) {
+ $fileCount++
+ $percentComplete = [math]::Round(($fileCount / $totalFiles) * 100, 1)
+
+ Write-Progress -Activity "Phase 3: Scanning for Missing Definitions" -Status "Scanning $($file.Name) ($fileCount of $totalFiles) - $($percentComplete)%" -PercentComplete $percentComplete
+
+ # Show periodic status updates
+ if ($fileCount % 10 -eq 0 -or $fileCount -eq $totalFiles) {
+ Write-Host " Processed $fileCount of $totalFiles files..." -ForegroundColor Gray
+ }
+
+ try {
+ $content = Get-Content $file.FullName -Raw -ErrorAction SilentlyContinue
+ if (-not $content) { continue }
+
+ # Pattern 1: {markup:Localize KeyName}
+ $matches = [regex]::Matches($content, '\{markup:Localize\s+([^}]+)\}')
+ foreach ($match in $matches) {
+ $key = $match.Groups[1].Value.Trim()
+ if ($key -notin $resourceKeys -and $key -notin $missingKeys) {
+ $missingKeys += $key
+ $missingDetails += @{
+ Key = $key
+ File = $file.Name
+ Pattern = "{markup:Localize $key}"
+ }
+ }
+ }
+
+ # Pattern 2: GetString("KeyName")
+ $matches = [regex]::Matches($content, 'GetString\s*\(\s*"([^"]+)"\s*\)')
+ foreach ($match in $matches) {
+ $key = $match.Groups[1].Value
+ if ($key -notin $resourceKeys -and $key -notin $missingKeys) {
+ $missingKeys += $key
+ $missingDetails += @{
+ Key = $key
+ File = $file.Name
+ Pattern = "GetString(`"$key`")"
+ }
+ }
+ }
+
+ # Pattern 3: Resources.KeyName (exclude common properties)
+ $matches = [regex]::Matches($content, 'Resources\.([A-Za-z_][A-Za-z0-9_]*)')
+ foreach ($match in $matches) {
+ $key = $match.Groups[1].Value
+ if ($key -notin @("ResourceManager", "Culture", "GetString", "Resources") -and
+ $key -notin $resourceKeys -and $key -notin $missingKeys) {
+ $missingKeys += $key
+ $missingDetails += @{
+ Key = $key
+ File = $file.Name
+ Pattern = "Resources.$key"
+ }
+ }
+ }
+ }
+ catch {
+ # Skip files that can't be processed
+ continue
+ }
+}
+
+# Clear progress bar
+Write-Progress -Activity "Phase 3: Scanning for Missing Definitions" -Completed
+Write-Host "Completed scanning $totalFiles files for missing definitions." -ForegroundColor Gray
+
+# Filter out common false positives
+$actualMissingKeys = $missingKeys | Where-Object {
+ $_ -notin @("AssemblyAssociatedContentFileAttribute", "GetString", "Resources") -and
+ $_ -ne ""
+} | Sort-Object -Unique
+
+if ($actualMissingKeys.Count -gt 0) {
+ Write-Host
+ Write-Host "=== MISSING RESOURCE DEFINITIONS ===" -ForegroundColor Yellow
+ Write-Host "Found $($actualMissingKeys.Count) resource lookups without definitions:" -ForegroundColor Red
+ Write-Host
+
+ foreach ($key in $actualMissingKeys) {
+ Write-Host "Missing: $key" -ForegroundColor Red
+ # Show where it's referenced
+ $keyDetails = $missingDetails | Where-Object { $_.Key -eq $key }
+ foreach ($detail in $keyDetails) {
+ Write-Host " Used in: $($detail.File)" -ForegroundColor Blue -NoNewline
+ Write-Host " as $($detail.Pattern)"
+ }
+ Write-Host
+ }
+
+ Write-Host "These resource keys are referenced in code but not defined in Resources.resx" -ForegroundColor Yellow
+}
+else {
+ Write-Host "All resource lookups have corresponding definitions! ✓" -ForegroundColor Green
+}
+
+Write-Host
+Write-Host "=== FINAL SUMMARY ===" -ForegroundColor Cyan
+Write-Host "Used resource keys: $($usedKeys.Count)" -ForegroundColor Green
+Write-Host "Unused resource keys: $($unusedKeys.Count)" -ForegroundColor Red
+Write-Host "Missing definitions: $($actualMissingKeys.Count)" -ForegroundColor Red
+
+if ($unusedKeys.Count -gt 0 -or $actualMissingKeys.Count -gt 0) {
+ Write-Host
+ Write-Host "⚠️ Resource issues found. Consider cleaning up unused resources and adding missing definitions." -ForegroundColor Yellow
+}
+else {
+ Write-Host
+ Write-Host "✅ All resource strings are properly managed!" -ForegroundColor Green
+}
+
+Write-Host
+Write-Host "Analysis complete." -ForegroundColor Cyan
\ No newline at end of file
diff --git a/ci/release.ps1 b/ci/release.ps1
new file mode 100644
index 0000000..3122ff6
--- /dev/null
+++ b/ci/release.ps1
@@ -0,0 +1,77 @@
+#!/usr/bin/env pwsh
+
+# OSDP-Bench Release Script
+# Merges develop into main to trigger CI version bump and release
+
+Write-Host "OSDP-Bench Release Process" -ForegroundColor Cyan
+Write-Host "==========================" -ForegroundColor Cyan
+Write-Host ""
+
+# Ensure we have latest changes
+Write-Host "Fetching latest changes..." -ForegroundColor Yellow
+git fetch --all
+
+# Check if there are uncommitted changes
+$uncommittedChanges = git status -s
+if ($uncommittedChanges) {
+ Write-Host "Error: You have uncommitted changes. Please commit or stash them before releasing." -ForegroundColor Red
+ exit 1
+}
+
+# Ensure we're on develop branch
+$currentBranch = git rev-parse --abbrev-ref HEAD
+if ($currentBranch -ne "develop") {
+ Write-Host "Error: You must be on the develop branch to release. Currently on: $currentBranch" -ForegroundColor Red
+ exit 1
+}
+
+# Pull latest develop
+Write-Host "Updating develop branch..." -ForegroundColor Yellow
+git pull origin develop
+
+# Check if develop is ahead of main
+$aheadCount = git rev-list --count origin/main..origin/develop
+if ($aheadCount -eq 0) {
+ Write-Host "Error: develop branch is not ahead of main. Nothing to release." -ForegroundColor Red
+ exit 1
+}
+
+Write-Host ""
+Write-Host "Changes to be released:" -ForegroundColor Green
+git log --oneline --no-merges origin/main..origin/develop
+
+Write-Host ""
+$confirm = Read-Host "Do you want to proceed with the release? (y/n)"
+if ($confirm -ne "y") {
+ Write-Host "Release cancelled." -ForegroundColor Yellow
+ exit 0
+}
+
+# Checkout main
+Write-Host "Checking out main branch..." -ForegroundColor Yellow
+git checkout main
+
+# Pull latest main
+Write-Host "Updating main branch..." -ForegroundColor Yellow
+git pull origin main
+
+# Merge develop
+Write-Host "Merging develop into main..." -ForegroundColor Yellow
+git merge --no-ff develop -m "Release: Merge develop into main for automated release"
+
+# Push to remote
+Write-Host "Pushing to remote..." -ForegroundColor Yellow
+git push origin main
+
+# Switch back to develop
+Write-Host "Switching back to develop branch..." -ForegroundColor Yellow
+git checkout develop
+
+Write-Host ""
+Write-Host "Release process completed successfully!" -ForegroundColor Green
+Write-Host "The CI pipeline will automatically:" -ForegroundColor Green
+Write-Host "1. Run tests" -ForegroundColor Green
+Write-Host "2. Bump version number" -ForegroundColor Green
+Write-Host "3. Create a tagged release" -ForegroundColor Green
+Write-Host ""
+Write-Host "You can monitor the release progress in Azure DevOps." -ForegroundColor Green
\ No newline at end of file
diff --git a/ci/release.sh b/ci/release.sh
deleted file mode 100755
index 7255a61..0000000
--- a/ci/release.sh
+++ /dev/null
@@ -1,76 +0,0 @@
-#!/bin/bash
-
-# OSDP-Bench Release Script
-# Merges develop into main to trigger CI version bump and release
-
-echo "OSDP-Bench Release Process"
-echo "=========================="
-echo ""
-
-# Ensure we have latest changes
-echo "Fetching latest changes..."
-git fetch --all
-
-# Check if there are uncommitted changes
-if [[ -n $(git status -s) ]]; then
- echo "Error: You have uncommitted changes. Please commit or stash them before releasing."
- exit 1
-fi
-
-# Ensure we're on develop branch
-CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
-if [[ "$CURRENT_BRANCH" != "develop" ]]; then
- echo "Error: You must be on the develop branch to release. Currently on: $CURRENT_BRANCH"
- exit 1
-fi
-
-# Pull latest develop
-echo "Updating develop branch..."
-git pull origin develop
-
-# Check if develop is ahead of main
-AHEAD_COUNT=$(git rev-list --count origin/main..origin/develop)
-if [[ "$AHEAD_COUNT" -eq 0 ]]; then
- echo "Error: develop branch is not ahead of main. Nothing to release."
- exit 1
-fi
-
-echo ""
-echo "Changes to be released:"
-git log --oneline --no-merges origin/main..origin/develop
-
-echo ""
-read -p "Do you want to proceed with the release? (y/n) " CONFIRM
-if [[ "$CONFIRM" != "y" ]]; then
- echo "Release cancelled."
- exit 0
-fi
-
-# Checkout main
-echo "Checking out main branch..."
-git checkout main
-
-# Pull latest main
-echo "Updating main branch..."
-git pull origin main
-
-# Merge develop
-echo "Merging develop into main..."
-git merge --no-ff develop -m "Release: Merge develop into main for automated release"
-
-# Push to remote
-echo "Pushing to remote..."
-git push origin main
-
-# Switch back to develop
-echo "Switching back to develop branch..."
-git checkout develop
-
-echo ""
-echo "Release process completed successfully!"
-echo "The CI pipeline will automatically:"
-echo "1. Run tests"
-echo "2. Bump version number"
-echo "3. Create a tagged release"
-echo ""
-echo "You can monitor the release progress in Azure DevOps."
\ No newline at end of file
diff --git a/docs/CLAUDE.md b/docs/CLAUDE.md
index b66db58..bb9b0ab 100644
--- a/docs/CLAUDE.md
+++ b/docs/CLAUDE.md
@@ -14,6 +14,32 @@
- Run specific test: `dotnet test test/Core.Tests/Core.Tests.csproj --filter "Name=ConnectViewModel_InitializedAvailableBaudRates"`
- Run with code coverage: `dotnet test test/Core.Tests/Core.Tests.csproj --collect:"XPlat Code Coverage"`
+## Resource Management
+- Check resource usage: `pwsh ci/check_resource_usage_progress.ps1`
+- The script analyzes unused resource strings and missing definitions across all language files
+- Shows progress indicators for both resource usage checking and missing definition scanning
+- Provides detailed reports with resource values and comments for cleanup decisions
+- Can be integrated into Azure DevOps pipelines using `ci/azure-pipeline-resource-check.yml`
+
+## Release Process
+- Create a release: `pwsh ci/release.ps1`
+- The script automates the release workflow:
+ - Validates working directory state (no uncommitted changes)
+ - Ensures you're on the develop branch
+ - Fetches latest changes from remote
+ - Verifies develop is ahead of main
+ - Shows commits to be released
+ - Merges develop into main with no-fast-forward
+ - Pushes to trigger CI/CD pipeline
+- The Azure DevOps pipeline will automatically:
+ - Run tests
+ - Bump version number
+ - Create a tagged release
+- Requirements:
+ - Must be on develop branch
+ - No uncommitted changes
+ - Develop must be ahead of main
+
## Code Style Guidelines
- Use C# 8.0+ features with async/await patterns for asynchronous operations
- Follow the MVVM design pattern for view models with ObservableObject and RelayCommand
@@ -31,9 +57,11 @@
## UI Style Guidelines
- **Always use standard styles** - Apply predefined styles from the design system instead of inline properties
- **Use design tokens for spacing** - Reference `{StaticResource Margin.Card}` instead of hardcoding values
-- **Apply semantic colors** - Use `{StaticResource Brush.Error}` instead of hardcoded colors like "Red"
+- **Apply theme-aware semantic colors** - Use `{DynamicResource SemanticSuccessBrush}` for automatic light/dark theme support
- **Follow the style hierarchy** - Check ComponentStyles.xaml and LayoutTemplates.xaml before creating custom styles
- **Update existing code** - When modifying files, replace inline styling with standard styles
- **Create reusable patterns** - If you find yourself repeating XAML structures, consider adding a new style or template
+- **Use WrapPanel for responsive layouts** - When controls should be horizontal on wide screens but wrap to vertical on narrow screens, use WrapPanel instead of fixed Grid layouts
+- **Prefer dynamic resources for colors** - Use `{DynamicResource}` instead of `{StaticResource}` for colors to ensure theme compatibility
For detailed UI styling guidelines and examples, see: `src/UI/Windows/Styles/StyleGuide.md`
diff --git a/docs/SYSTEM_LANGUAGE_CHECK.md b/docs/SYSTEM_LANGUAGE_CHECK.md
new file mode 100644
index 0000000..1de7226
--- /dev/null
+++ b/docs/SYSTEM_LANGUAGE_CHECK.md
@@ -0,0 +1,149 @@
+# System Language Matching
+
+This document describes the system language matching functionality added to OSDP-Bench.
+
+## Overview
+
+The localization service now provides methods to check if the application's current language matches the system language. This can be useful for:
+- Notifying users when their app language differs from the system
+- Providing an option to sync with system language
+- Analytics to understand user language preferences
+
+## New API Methods
+
+### `IsSystemLanguageMatch()`
+Checks if the current application language matches the system language.
+
+```csharp
+bool isMatch = _localizationService.IsSystemLanguageMatch();
+```
+
+Returns `true` if:
+- The system language is not supported by the application (no mismatch to report)
+- The culture names are exactly the same (e.g., "en-US" == "en-US")
+- The base languages match (e.g., "en-US" matches "en-GB")
+
+### `GetSystemCulture()`
+Gets the current system UI culture.
+
+```csharp
+CultureInfo systemCulture = _localizationService.GetSystemCulture();
+```
+
+### `IsCultureSupported(CultureInfo culture)`
+Checks if a specific culture is supported by the application.
+
+```csharp
+bool isSupported = _localizationService.IsCultureSupported(systemCulture);
+```
+
+Returns `true` if the culture or its base language is supported by the application.
+
+## Usage Examples
+
+### Example 1: Display System Language Mismatch Indicator
+```csharp
+public class LanguageStatusViewModel : ObservableObject
+{
+ private readonly ILocalizationService _localizationService;
+
+ public bool IsSystemLanguageMismatch => !_localizationService.IsSystemLanguageMatch();
+
+ public string SystemLanguageName => _localizationService.GetSystemCulture().NativeName;
+
+ public LanguageStatusViewModel(ILocalizationService localizationService)
+ {
+ _localizationService = localizationService;
+ _localizationService.CultureChanged += (s, e) => OnPropertyChanged(nameof(IsSystemLanguageMismatch));
+ }
+}
+```
+
+### Example 2: Prompt User on Language Mismatch
+```csharp
+public async Task CheckLanguageOnStartupAsync()
+{
+ if (!_localizationService.IsSystemLanguageMatch())
+ {
+ var systemCulture = _localizationService.GetSystemCulture();
+ var result = await _dialogService.ShowMessageAsync(
+ $"Your system language is {systemCulture.NativeName}. " +
+ "Would you like to switch the application to match?",
+ "Language Mismatch",
+ DialogButtons.YesNo);
+
+ if (result == DialogResult.Yes)
+ {
+ _localizationService.ChangeCulture(systemCulture);
+ }
+ }
+}
+```
+
+### Example 3: Add "Use System Language" Option
+```csharp
+public class LanguageSelectionViewModel : ObservableObject
+{
+ [RelayCommand]
+ private void UseSystemLanguage()
+ {
+ var systemCulture = _localizationService.GetSystemCulture();
+ _localizationService.ChangeCulture(systemCulture);
+ }
+
+ public bool IsUsingSystemLanguage => _localizationService.IsSystemLanguageMatch();
+}
+```
+
+## Implementation Notes
+
+1. **System Culture Detection**: Uses `CultureInfo.InstalledUICulture` which represents the OS display language
+2. **Flexible Matching**: Considers both exact matches and base language matches
+3. **Real-time Updates**: The `IsSystemLanguageMatch()` method always checks against the current system state
+
+## UI Integration
+
+The system language prompt has been integrated into the application startup process. Here's how it works:
+
+### Automatic Detection
+- When the application starts, it automatically checks if the system language matches the current app language
+- The check only runs for users who have previously set a language preference (not first-time users)
+- If the system language is not supported by the app, no prompt is shown
+
+### User Experience
+1. **Language Mismatch Detected**: A dialog appears with the title "System Language Detected"
+2. **Informative Message**: Shows "Your system language is [Language Name]. Would you like to switch the application to match your system language?"
+3. **User Choice**: User can choose "OK" to switch or "Cancel" to keep current language
+4. **Automatic Switching**: If user chooses "OK", the app immediately switches to the best matching supported language
+
+### Implementation Details
+- **Service**: `LanguageMismatchService` handles all the logic
+- **Timing**: Check runs 500ms after startup to ensure UI is fully loaded
+- **Language Matching**: Uses exact match first, then falls back to base language match (e.g., "en-GB" → "en-US")
+- **Persistence**: Language choice is automatically saved to user settings
+
+## Testing
+
+To test the system language prompt:
+
+### Test Case 1: Language Mismatch
+1. Set Windows display language to Spanish (Settings > Time & Language > Language)
+2. Set OSDP-Bench to English in the Info page
+3. Close and relaunch the application
+4. You should see the system language prompt asking to switch to Spanish
+
+### Test Case 2: No Prompt for Unsupported Language
+1. Set Windows display language to Italian (not supported by the app)
+2. Set OSDP-Bench to English
+3. Close and relaunch the application
+4. No prompt should appear (Italian is not supported)
+
+### Test Case 3: First-Time User
+1. Delete the settings file (`%APPDATA%\OSDPBench\settings.json`)
+2. Launch the application
+3. No prompt should appear (first-time users get system language by default)
+
+### Test Case 4: Languages Already Match
+1. Set both Windows and OSDP-Bench to the same language
+2. Relaunch the application
+3. No prompt should appear (languages already match)
\ No newline at end of file
diff --git a/src/Assets/google-play.svg b/src/Assets/google-play.svg
new file mode 100644
index 0000000..223ebd2
--- /dev/null
+++ b/src/Assets/google-play.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/Core/Actions/FileTransferAction.cs b/src/Core/Actions/FileTransferAction.cs
index 9ef4750..24439f9 100644
--- a/src/Core/Actions/FileTransferAction.cs
+++ b/src/Core/Actions/FileTransferAction.cs
@@ -20,7 +20,7 @@ public async Task PerformAction(ControlPanel panel, Guid connectionId, b
{
if (parameter is not FileTransferParameters transferParams)
{
- throw new ArgumentException("Invalid parameter type for file transfer", nameof(parameter));
+ throw new ArgumentException(@"Invalid parameter type for file transfer", nameof(parameter));
}
if (string.IsNullOrEmpty(transferParams.FilePath))
diff --git a/src/Core/Actions/ResetCypressDeviceAction.cs b/src/Core/Actions/ResetCypressDeviceAction.cs
index 7ace2f4..5ef4be5 100644
--- a/src/Core/Actions/ResetCypressDeviceAction.cs
+++ b/src/Core/Actions/ResetCypressDeviceAction.cs
@@ -21,7 +21,7 @@ public async Task PerformAction(ControlPanel panel, Guid connectionId, b
await panel.Shutdown();
var connectionService = parameter as IOsdpConnection ??
- throw new ArgumentException("Invalid type", nameof(parameter));
+ throw new ArgumentException(@"Invalid type", nameof(parameter));
connectionId = panel.StartConnection(connectionService, TimeSpan.Zero);
diff --git a/src/Core/Actions/SetCommunicationAction.cs b/src/Core/Actions/SetCommunicationAction.cs
index 26bcc8e..408e0a1 100644
--- a/src/Core/Actions/SetCommunicationAction.cs
+++ b/src/Core/Actions/SetCommunicationAction.cs
@@ -20,7 +20,7 @@ public async Task PerformAction(ControlPanel panel, Guid connectionId, b
object? parameter)
{
var communicationParameters = parameter as CommunicationParameters ??
- throw new ArgumentException("Invalid type", nameof(parameter));
+ throw new ArgumentException(@"Invalid type", nameof(parameter));
var result = await panel.CommunicationConfiguration(connectionId, address,
new CommunicationConfiguration(communicationParameters.Address,
diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj
index f21bfbe..8400539 100644
--- a/src/Core/Core.csproj
+++ b/src/Core/Core.csproj
@@ -25,7 +25,7 @@
-
+
diff --git a/src/Core/Models/UserSettings.cs b/src/Core/Models/UserSettings.cs
index a096732..e6fd223 100644
--- a/src/Core/Models/UserSettings.cs
+++ b/src/Core/Models/UserSettings.cs
@@ -13,15 +13,20 @@ public class UserSettings
///
/// Gets or sets the window width
///
- public double WindowWidth { get; set; } = 800;
+ public double WindowWidth { get; init; } = 800;
///
/// Gets or sets the window height
///
- public double WindowHeight { get; set; } = 600;
+ public double WindowHeight { get; init; } = 600;
///
/// Gets or sets whether the window is maximized
///
- public bool IsMaximized { get; set; } = false;
+ public bool IsMaximized { get; init; }
+
+ ///
+ /// Gets or sets whether to skip language mismatch checking
+ ///
+ public bool SkipLanguageMismatchCheck { get; set; }
}
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.de.resx b/src/Core/Resources/Resources.de.resx
index 5776725..269a102 100644
--- a/src/Core/Resources/Resources.de.resx
+++ b/src/Core/Resources/Resources.de.resx
@@ -122,45 +122,21 @@
Entfernt
Device connection status when not connected
-
- Entdeckend
- Device connection status during discovery process
-
Fehler
Device connection status when an error occurred
-
- USB-Gerät eingesteckt
- Message shown when a USB device is detected
-
-
- USB-Gerät entfernt
- Message shown when a USB device is disconnected
-
-
- Verbindung fehlgeschlagen
- Generic connection failure message
-
-
- Gerät nicht gefunden
- Error when device cannot be found during discovery
-
-
- Ungültige Adresse
- Error when the entered address is invalid
-
S/N -
Prefix for device serial number display
-
- Gerät, das an der Adresse verbunden ist {0} mit einer Baudrate von {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ Adresse {0} bei {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -314,10 +290,6 @@
Art
Column header for type in monitoring grid
-
- Details
- Column header for details in monitoring grid
-
Erweitern
Button text to expand row details
@@ -472,10 +444,6 @@
USB-Gerät getrennt
Message when USB device is disconnected
-
- USB-Anschlüsse geändert
- Message when USB ports have changed
-
Verbinden
@@ -557,8 +525,24 @@
Sprache auswählen
Tooltip for language selection
-
- Sprache erfolgreich geändert
- Confirmation message when language is changed
+
+ Systemsprache erkannt
+ Title for system language mismatch dialog
+
+
+ Ihre Systemsprache ist {0}. Möchten Sie die Anwendung an Ihre Systemsprache anpassen?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ Frag mich nicht noch einmal
+ Checkbox label to prevent future language mismatch prompts
+
+
+ Ja
+ Common Yes button text
+
+
+ Nein
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.es.resx b/src/Core/Resources/Resources.es.resx
index f53280d..5c400fe 100644
--- a/src/Core/Resources/Resources.es.resx
+++ b/src/Core/Resources/Resources.es.resx
@@ -122,45 +122,21 @@
Desconectar
Device connection status when not connected
-
- Descubriendo
- Device connection status during discovery process
-
Error
Device connection status when an error occurred
-
- Dispositivo USB conectado
- Message shown when a USB device is detected
-
-
- Dispositivo USB extraído
- Message shown when a USB device is disconnected
-
-
- Error de conexión
- Generic connection failure message
-
-
- Dispositivo no encontrado
- Error when device cannot be found during discovery
-
-
- Dirección no válida
- Error when the entered address is invalid
-
S/N -
Prefix for device serial number display
-
- Dispositivo conectado a la dirección {0} funcionando a una velocidad de transmisión de {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ Dirección {0} en {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -314,10 +290,6 @@
Tipo
Column header for type in monitoring grid
-
- Detalles
- Column header for details in monitoring grid
-
Expandir
Button text to expand row details
@@ -472,10 +444,6 @@
Dispositivo USB desconectado
Message when USB device is disconnected
-
- Puertos USB cambiados
- Message when USB ports have changed
-
Conectar
@@ -557,8 +525,24 @@
Seleccionar idioma
Tooltip for language selection
-
- El lenguaje cambió con éxito
- Confirmation message when language is changed
+
+ Idioma del sistema detectado
+ Title for system language mismatch dialog
+
+
+ El idioma de su sistema es {0}. ¿Le gustaría cambiar la aplicación para que coincida con el idioma de su sistema?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ No me vuelvas a preguntar
+ Checkbox label to prevent future language mismatch prompts
+
+
+ Sí
+ Common Yes button text
+
+
+ No
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.fr.resx b/src/Core/Resources/Resources.fr.resx
index fbc0ba0..b2acdf9 100644
--- a/src/Core/Resources/Resources.fr.resx
+++ b/src/Core/Resources/Resources.fr.resx
@@ -122,45 +122,21 @@
Coupé
Device connection status when not connected
-
- Découvrir
- Device connection status during discovery process
-
Erreur
Device connection status when an error occurred
-
- Périphérique USB inséré
- Message shown when a USB device is detected
-
-
- Périphérique USB supprimé
- Message shown when a USB device is disconnected
-
-
- Échec de la connexion
- Generic connection failure message
-
-
- Appareil introuvable
- Error when device cannot be found during discovery
-
-
- Adresse invalide
- Error when the entered address is invalid
-
N° de série -
Prefix for device serial number display
-
- Appareil connecté à l’adresse {0} fonctionnant à une vitesse de transmission de {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ Adresse {0} à {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -314,10 +290,6 @@
Type
Column header for type in monitoring grid
-
- Détails
- Column header for details in monitoring grid
-
Développer
Button text to expand row details
@@ -472,10 +444,6 @@
Périphérique USB déconnecté
Message when USB device is disconnected
-
- Ports USB modifiés
- Message when USB ports have changed
-
Relier
@@ -557,8 +525,24 @@
Sélectionner une langue
Tooltip for language selection
-
- Changement de langue réussi
- Confirmation message when language is changed
+
+ Langue du système détectée
+ Title for system language mismatch dialog
+
+
+ La langue de votre système est {0}. Souhaitez-vous changer l’application pour qu’elle corresponde à la langue de votre système ?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ Ne me demandez plus
+ Checkbox label to prevent future language mismatch prompts
+
+
+ Oui
+ Common Yes button text
+
+
+ Non
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.ja.resx b/src/Core/Resources/Resources.ja.resx
index f4a2f6d..e79ab41 100644
--- a/src/Core/Resources/Resources.ja.resx
+++ b/src/Core/Resources/Resources.ja.resx
@@ -122,45 +122,21 @@
途切れ途切れ
Device connection status when not connected
-
- 発見
- Device connection status during discovery process
-
エラー
Device connection status when an error occurred
-
- USBデバイスが挿入されています
- Message shown when a USB device is detected
-
-
- USBデバイスを取り外しました
- Message shown when a USB device is disconnected
-
-
- 接続に失敗しました
- Generic connection failure message
-
-
- デバイスが見つかりません
- Error when device cannot be found during discovery
-
-
- 無効なアドレス
- Error when the entered address is invalid
-
S/N -
Prefix for device serial number display
-
- アドレスで接続されたデバイス {0} ボーレート {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ 住所 {0} で {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -314,10 +290,6 @@
種類
Column header for type in monitoring grid
-
- 細部
- Column header for details in monitoring grid
-
膨らむ
Button text to expand row details
@@ -472,10 +444,6 @@
USBデバイスが切断されました
Message when USB device is disconnected
-
- USBポートの変更
- Message when USB ports have changed
-
繋ぐ
@@ -557,8 +525,24 @@
言語の選択
Tooltip for language selection
-
- 言語が正常に変更されました
- Confirmation message when language is changed
+
+ システム言語が検出されました
+ Title for system language mismatch dialog
+
+
+ システム言語は次のとおりです。 {0}.システム言語に合わせてアプリケーションを切り替えますか?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ 二度と聞かないで
+ Checkbox label to prevent future language mismatch prompts
+
+
+ はい
+ Common Yes button text
+
+
+ いいえ
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.resx b/src/Core/Resources/Resources.resx
index 38473df..cf8218c 100644
--- a/src/Core/Resources/Resources.resx
+++ b/src/Core/Resources/Resources.resx
@@ -123,38 +123,14 @@
Disconnected
Device connection status when not connected
-
- Discovering
- Device connection status during discovery process
-
Error
Device connection status when an error occurred
-
- USB device inserted
- Message shown when a USB device is detected
-
-
- USB device removed
- Message shown when a USB device is disconnected
-
-
- Connection failed
- Generic connection failure message
-
-
- Device not found
- Error when device cannot be found during discovery
-
-
- Invalid address
- Error when the entered address is invalid
-
@@ -163,9 +139,9 @@
-
- Device connected at address {0} running at a baud rate of {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ Address {0} at {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -323,10 +299,6 @@
Type
Column header for type in monitoring grid
-
- Details
- Column header for details in monitoring grid
-
Expand
Button text to expand row details
@@ -487,10 +459,6 @@
USB device disconnected
Message when USB device is disconnected
-
- USB ports changed
- Message when USB ports have changed
-
@@ -577,8 +545,24 @@
Select Language
Tooltip for language selection
-
- Language changed successfully
- Confirmation message when language is changed
+
+ System Language Detected
+ Title for system language mismatch dialog
+
+
+ Your system language is {0}. Would you like to switch the application to match your system language?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ Don't ask me again
+ Checkbox label to prevent future language mismatch prompts
+
+
+ Yes
+ Common Yes button text
+
+
+ No
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Resources/Resources.zh.resx b/src/Core/Resources/Resources.zh.resx
index b7df891..01d694c 100644
--- a/src/Core/Resources/Resources.zh.resx
+++ b/src/Core/Resources/Resources.zh.resx
@@ -122,45 +122,21 @@
断开
Device connection status when not connected
-
- 发现
- Device connection status during discovery process
-
错误
Device connection status when an error occurred
-
- 已插入 USB 设备
- Message shown when a USB device is detected
-
-
- 已删除 USB 设备
- Message shown when a USB device is disconnected
-
-
- 连接失败
- Generic connection failure message
-
-
- 未找到设备
- Error when device cannot be found during discovery
-
-
- 地址无效
- Error when the entered address is invalid
-
序列号 -
Prefix for device serial number display
-
- 设备连接地址 {0} 以 {1}
- Format string for displaying connection details. {0} = address, {1} = baud rate
+
+ 地址 {0} 在 {1}
+ Brief connection status format. {0} = address, {1} = baud rate
@@ -314,10 +290,6 @@
类型
Column header for type in monitoring grid
-
- 详
- Column header for details in monitoring grid
-
扩大
Button text to expand row details
@@ -472,10 +444,6 @@
USB 设备已断开连接
Message when USB device is disconnected
-
- USB 端口已更改
- Message when USB ports have changed
-
连接
@@ -557,8 +525,24 @@
选择语言
Tooltip for language selection
-
- 语言更改成功
- Confirmation message when language is changed
+
+ 检测到系统语言
+ Title for system language mismatch dialog
+
+
+ 您的系统语言是 {0}.是否要切换应用程序以匹配您的系统语言?
+ Message asking user if they want to switch to system language. {0} is the system language name.
+
+
+ 不要再问我了
+ Checkbox label to prevent future language mismatch prompts
+
+
+ 是的
+ Common Yes button text
+
+
+ 不
+ Common No button text
\ No newline at end of file
diff --git a/src/Core/Services/DeviceManagementService.cs b/src/Core/Services/DeviceManagementService.cs
index 46fe062..75f9821 100644
--- a/src/Core/Services/DeviceManagementService.cs
+++ b/src/Core/Services/DeviceManagementService.cs
@@ -222,20 +222,7 @@ public async Task Shutdown()
await _panel.Shutdown();
- try
- {
- await WaitUntilDeviceIsOffline();
- }
- catch (TimeoutException ex)
- {
- // Log or handle the timeout exception
- Console.WriteLine($"Warning: {ex.Message}");
- }
- catch (Exception ex)
- {
- // Log unexpected exceptions during shutdown
- Console.WriteLine($"Error during device shutdown: {ex.Message}");
- }
+ await WaitUntilDeviceIsOffline();
}
private async Task WaitUntilDeviceIsOffline()
diff --git a/src/Core/Services/DeviceStateService.cs b/src/Core/Services/DeviceStateService.cs
index 1aaaab5..7eb215c 100644
--- a/src/Core/Services/DeviceStateService.cs
+++ b/src/Core/Services/DeviceStateService.cs
@@ -22,22 +22,22 @@ public DeviceStateService(IDeviceManagementService deviceManagementService)
throw new ArgumentNullException(nameof(deviceManagementService));
// Forward events from the device management service
- _deviceManagementService.ConnectionStatusChange += (sender, args) =>
+ _deviceManagementService.ConnectionStatusChange += (_, args) =>
ConnectionStatusChange?.Invoke(this, args);
- _deviceManagementService.KeypadReadReceived += (sender, args) =>
+ _deviceManagementService.KeypadReadReceived += (_, args) =>
KeypadReadReceived?.Invoke(this, args);
- _deviceManagementService.CardReadReceived += (sender, args) =>
+ _deviceManagementService.CardReadReceived += (_, args) =>
CardReadReceived?.Invoke(this, args);
- _deviceManagementService.TraceEntryReceived += (sender, args) =>
+ _deviceManagementService.TraceEntryReceived += (_, args) =>
TraceEntryReceived?.Invoke(this, args);
- _deviceManagementService.NakReplyReceived += (sender, args) =>
+ _deviceManagementService.NakReplyReceived += (_, args) =>
NakReplyReceived?.Invoke(this, args);
- _deviceManagementService.DeviceLookupsChanged += (sender, args) =>
+ _deviceManagementService.DeviceLookupsChanged += (_, args) =>
DeviceLookupsChanged?.Invoke(this, args);
}
diff --git a/src/Core/Services/ILanguageMismatchService.cs b/src/Core/Services/ILanguageMismatchService.cs
new file mode 100644
index 0000000..b3a47d5
--- /dev/null
+++ b/src/Core/Services/ILanguageMismatchService.cs
@@ -0,0 +1,19 @@
+namespace OSDPBench.Core.Services;
+
+///
+/// Service for handling system language mismatch detection and user prompts
+///
+public interface ILanguageMismatchService
+{
+ ///
+ /// Checks for system language mismatch and prompts the user if needed
+ ///
+ Task CheckAndPromptForLanguageMismatchAsync();
+
+ ///
+ /// Shows the language mismatch dialog with custom UI
+ ///
+ /// The name of the system language
+ /// A tuple containing (userWantsToSwitch, dontAskAgain)
+ Task<(bool userWantsToSwitch, bool dontAskAgain)> ShowLanguageMismatchDialogAsync(string systemLanguageName);
+}
\ No newline at end of file
diff --git a/src/Core/Services/ILocalizationService.cs b/src/Core/Services/ILocalizationService.cs
index 5daffba..31cc258 100644
--- a/src/Core/Services/ILocalizationService.cs
+++ b/src/Core/Services/ILocalizationService.cs
@@ -55,4 +55,23 @@ public interface ILocalizationService
/// The culture to get the display name for
/// The localized display name
string GetCultureDisplayName(CultureInfo culture);
+
+ ///
+ /// Checks if the current application language matches the system language
+ ///
+ /// True if the languages match, false otherwise
+ bool IsSystemLanguageMatch();
+
+ ///
+ /// Gets the current system language
+ ///
+ /// The system's current UI culture
+ CultureInfo GetSystemCulture();
+
+ ///
+ /// Checks if a specific culture is supported by the application
+ ///
+ /// The culture to check
+ /// True if the culture or its base language is supported
+ bool IsCultureSupported(CultureInfo culture);
}
\ No newline at end of file
diff --git a/src/Core/Services/IUsbDeviceMonitorService.cs b/src/Core/Services/IUsbDeviceMonitorService.cs
index 3d93ccd..9a199bf 100644
--- a/src/Core/Services/IUsbDeviceMonitorService.cs
+++ b/src/Core/Services/IUsbDeviceMonitorService.cs
@@ -1,5 +1,3 @@
-using System;
-
namespace OSDPBench.Core.Services;
///
diff --git a/src/Core/Services/LanguageMismatchService.cs b/src/Core/Services/LanguageMismatchService.cs
new file mode 100644
index 0000000..c94630d
--- /dev/null
+++ b/src/Core/Services/LanguageMismatchService.cs
@@ -0,0 +1,115 @@
+using System.Globalization;
+
+namespace OSDPBench.Core.Services;
+
+///
+/// Service for handling system language mismatch detection and user prompts
+///
+public class LanguageMismatchService : ILanguageMismatchService
+{
+ private readonly ILocalizationService _localizationService;
+ private readonly IDialogService _dialogService;
+ private readonly IUserSettingsService _userSettingsService;
+
+ ///
+ /// Initializes a new instance of the LanguageMismatchService
+ ///
+ /// The localization service
+ /// The dialog service
+ /// The user settings service
+ public LanguageMismatchService(
+ ILocalizationService localizationService,
+ IDialogService dialogService,
+ IUserSettingsService userSettingsService)
+ {
+ _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
+ _dialogService = dialogService ?? throw new ArgumentNullException(nameof(dialogService));
+ _userSettingsService = userSettingsService ?? throw new ArgumentNullException(nameof(userSettingsService));
+ }
+
+ ///
+ public async Task CheckAndPromptForLanguageMismatchAsync()
+ {
+ // Only check if this is not the user's first time setting a language
+ // (i.e., they have a saved preference)
+ if (string.IsNullOrEmpty(_userSettingsService.Settings.PreferredCulture))
+ {
+ // First time user - don't prompt, just use system language
+ return;
+ }
+
+ // Check if user has disabled language mismatch checking
+ if (_userSettingsService.Settings.SkipLanguageMismatchCheck)
+ {
+ // User has opted out of language mismatch checks
+ return;
+ }
+
+ // Check if there's a mismatch
+ if (_localizationService.IsSystemLanguageMatch())
+ {
+ // Languages match or system language not supported - no action needed
+ return;
+ }
+
+ var systemCulture = _localizationService.GetSystemCulture();
+ var systemLanguageName = systemCulture.NativeName;
+
+ // Show custom dialog
+ var (userWantsToSwitch, dontAskAgain) = await ShowLanguageMismatchDialogAsync(systemLanguageName);
+
+ // Save the "don't ask again" preference
+ if (dontAskAgain)
+ {
+ await _userSettingsService.UpdateSettingsAsync(settings =>
+ settings.SkipLanguageMismatchCheck = true);
+ }
+
+ if (userWantsToSwitch)
+ {
+ // Find the best supported culture that matches the system language
+ var supportedCulture = FindBestMatchingCulture(systemCulture);
+ if (supportedCulture != null)
+ {
+ _localizationService.ChangeCulture(supportedCulture);
+ }
+ }
+ }
+
+ ///
+ public async Task<(bool userWantsToSwitch, bool dontAskAgain)> ShowLanguageMismatchDialogAsync(string systemLanguageName)
+ {
+ // This method will be implemented in the Windows-specific service
+ // For now, fall back to the simple dialog
+ var title = _localizationService.GetString("Language_SystemMismatchTitle");
+ var message = _localizationService.GetString("Language_SystemMismatchMessage", systemLanguageName);
+
+ var userWantsToSwitch = await _dialogService.ShowConfirmationDialog(
+ title,
+ message,
+ MessageIcon.Information);
+
+ return (userWantsToSwitch, false); // No "don't ask again" option in fallback
+ }
+
+ ///
+ /// Finds the best matching supported culture for the given system culture
+ ///
+ /// The system culture to match
+ /// The best matching supported culture, or null if none found
+ private CultureInfo? FindBestMatchingCulture(CultureInfo systemCulture)
+ {
+ var supportedCultures = _localizationService.SupportedCultures;
+
+ // First try exact match
+ var exactMatch = supportedCultures.FirstOrDefault(c => c.Name == systemCulture.Name);
+ if (exactMatch != null)
+ return exactMatch;
+
+ // Then try base language match
+ var baseLanguageMatch = supportedCultures.FirstOrDefault(c =>
+ c.TwoLetterISOLanguageName == systemCulture.TwoLetterISOLanguageName);
+
+ return baseLanguageMatch;
+ }
+}
\ No newline at end of file
diff --git a/src/Core/Services/LocalizationService.cs b/src/Core/Services/LocalizationService.cs
index aad0743..088c570 100644
--- a/src/Core/Services/LocalizationService.cs
+++ b/src/Core/Services/LocalizationService.cs
@@ -1,6 +1,4 @@
using System.Globalization;
-using System.Resources;
-using OSDPBench.Core.Resources;
namespace OSDPBench.Core.Services;
@@ -9,7 +7,6 @@ namespace OSDPBench.Core.Services;
///
public class LocalizationService : ILocalizationService
{
- private readonly ResourceManager _resourceManager;
private readonly IUserSettingsService? _userSettingsService;
private CultureInfo _currentCulture;
@@ -19,7 +16,6 @@ public class LocalizationService : ILocalizationService
/// Optional user settings service for persistence
public LocalizationService(IUserSettingsService? userSettingsService)
{
- _resourceManager = new ResourceManager("OSDPBench.Core.Resources.Resources", typeof(LocalizationService).Assembly);
_userSettingsService = userSettingsService;
// Initialize culture from settings or system default
@@ -72,7 +68,7 @@ public CultureInfo CurrentCulture
///
public string GetString(string key)
{
- return OSDPBench.Core.Resources.Resources.GetString(key);
+ return Resources.Resources.GetString(key);
}
///
@@ -101,7 +97,7 @@ public void ChangeCulture(CultureInfo culture)
CultureInfo.CurrentCulture = culture;
// Update the Resources class culture (this will trigger PropertyChanged)
- OSDPBench.Core.Resources.Resources.ChangeCulture(culture);
+ Resources.Resources.ChangeCulture(culture);
// Save preference to settings
if (_userSettingsService != null)
@@ -138,4 +134,40 @@ public string GetCultureDisplayName(CultureInfo culture)
// Return the native name of the culture
return culture.NativeName;
}
+
+ ///
+ public bool IsSystemLanguageMatch()
+ {
+ var systemCulture = GetSystemCulture();
+
+ // If system language is not supported, consider it a match (no need to prompt)
+ if (!IsCultureSupported(systemCulture))
+ return true;
+
+ // Check if cultures are exactly the same
+ if (_currentCulture.Name == systemCulture.Name)
+ return true;
+
+ // Check if the base languages match (e.g., "en-US" matches "en-GB")
+ if (_currentCulture.TwoLetterISOLanguageName == systemCulture.TwoLetterISOLanguageName)
+ return true;
+
+ return false;
+ }
+
+ ///
+ public CultureInfo GetSystemCulture()
+ {
+ // Get the current system UI culture
+ // This represents the OS display language
+ return CultureInfo.InstalledUICulture;
+ }
+
+ ///
+ public bool IsCultureSupported(CultureInfo culture)
+ {
+ return SupportedCultures.Any(c =>
+ c.Name == culture.Name ||
+ c.TwoLetterISOLanguageName == culture.TwoLetterISOLanguageName);
+ }
}
\ No newline at end of file
diff --git a/src/Core/ViewModels/Dialogs/LanguageMismatchDialogViewModel.cs b/src/Core/ViewModels/Dialogs/LanguageMismatchDialogViewModel.cs
new file mode 100644
index 0000000..765f2cc
--- /dev/null
+++ b/src/Core/ViewModels/Dialogs/LanguageMismatchDialogViewModel.cs
@@ -0,0 +1,41 @@
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+
+namespace OSDPBench.Core.ViewModels.Dialogs;
+
+///
+/// ViewModel for the language mismatch dialog
+///
+public partial class LanguageMismatchDialogViewModel : ObservableObject
+{
+ private readonly Action _closeCallback;
+
+ [ObservableProperty]
+ private string _message;
+
+ [ObservableProperty]
+ private bool _dontAskAgain;
+
+ ///
+ /// Initializes a new instance of the LanguageMismatchDialogViewModel
+ ///
+ /// The message to display
+ /// Callback when dialog closes (userChoice, dontAskAgain)
+ public LanguageMismatchDialogViewModel(string message, Action closeCallback)
+ {
+ _message = message;
+ _closeCallback = closeCallback ?? throw new ArgumentNullException(nameof(closeCallback));
+ }
+
+ [RelayCommand]
+ private void Yes()
+ {
+ _closeCallback(true, DontAskAgain);
+ }
+
+ [RelayCommand]
+ private void No()
+ {
+ _closeCallback(false, DontAskAgain);
+ }
+}
\ No newline at end of file
diff --git a/src/Core/ViewModels/LanguageSelectionViewModel.cs b/src/Core/ViewModels/LanguageSelectionViewModel.cs
index 9ca5548..816eba6 100644
--- a/src/Core/ViewModels/LanguageSelectionViewModel.cs
+++ b/src/Core/ViewModels/LanguageSelectionViewModel.cs
@@ -3,7 +3,6 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using OSDPBench.Core.Services;
-using OSDPBench.Core.Resources;
namespace OSDPBench.Core.ViewModels;
diff --git a/src/Core/ViewModels/Pages/ConnectViewModel.cs b/src/Core/ViewModels/Pages/ConnectViewModel.cs
index 1ee8cdb..16d3435 100644
--- a/src/Core/ViewModels/Pages/ConnectViewModel.cs
+++ b/src/Core/ViewModels/Pages/ConnectViewModel.cs
@@ -5,7 +5,6 @@
using OSDP.Net.Tracing;
using OSDPBench.Core.Models;
using OSDPBench.Core.Services;
-using OSDPBench.Core.Resources;
namespace OSDPBench.Core.ViewModels.Pages;
@@ -57,13 +56,13 @@ public ConnectViewModel(IDialogService dialogService, IDeviceManagementService d
_usbDeviceMonitorService.StartMonitoring();
}
- // Perform initial port scan
+ // Perform an initial port scan
Task.Run(async () => await InitializeSerialPorts());
}
private void OnDeviceManagementServiceOnTraceEntryReceived(object? sender, TraceEntry traceEntry)
{
- // Update activity indicators based on raw trace entry direction (works for encrypted packets too)
+ // Update activity indicators based on a raw trace entry direction (works for encrypted packets too)
UpdateActivityIndicators(traceEntry.Direction);
PacketTraceEntry? packetTraceEntry = BuildPacketTraceEntry(traceEntry);
@@ -102,23 +101,23 @@ private void DeviceManagementServiceOnConnectionStatusChange(object? sender, Con
{
if (connectionStatus == ConnectionStatus.Connected)
{
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_Connected");
+ StatusText = Resources.Resources.GetString("Status_Connected");
NakText = string.Empty;
StatusLevel = StatusLevel.Connected;
}
else if (StatusLevel == StatusLevel.Discovered)
{
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToConnect");
+ StatusText = Resources.Resources.GetString("Status_AttemptingToConnect");
StatusLevel = StatusLevel.Connecting;
}
else if (connectionStatus == ConnectionStatus.InvalidSecurityKey)
{
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_InvalidSecurityKey");
+ StatusText = Resources.Resources.GetString("Status_InvalidSecurityKey");
StatusLevel = StatusLevel.Error;
}
else
{
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_Disconnected");
+ StatusText = Resources.Resources.GetString("Status_Disconnected");
StatusLevel = StatusLevel.Disconnected;
}
}
@@ -188,7 +187,7 @@ private async Task InitializeSerialPorts()
}
catch (Exception ex)
{
- Console.WriteLine(OSDPBench.Core.Resources.Resources.GetString("Error_InitializingSerialPorts").Replace("{0}", ex.Message));
+ Console.WriteLine(Resources.Resources.GetString("Error_InitializingSerialPorts").Replace("{0}", ex.Message));
StatusLevel = StatusLevel.NotReady;
_initializationComplete.SetException(ex);
}
@@ -230,27 +229,27 @@ private void UpdateDiscoveryStatus(DiscoveryResult current)
switch (current.Status)
{
case DiscoveryStatus.Started:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToDiscover");
+ StatusText = Resources.Resources.GetString("Status_AttemptingToDiscover");
break;
case DiscoveryStatus.LookingForDeviceOnConnection:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToDiscoverAtBaudRate").Replace("{0}", current.Connection.BaudRate.ToString());
+ StatusText = Resources.Resources.GetString("Status_AttemptingToDiscoverAtBaudRate").Replace("{0}", current.Connection.BaudRate.ToString());
break;
case DiscoveryStatus.ConnectionWithDeviceFound:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_FoundDeviceAtBaudRate").Replace("{0}", current.Connection.BaudRate.ToString());
+ StatusText = Resources.Resources.GetString("Status_FoundDeviceAtBaudRate").Replace("{0}", current.Connection.BaudRate.ToString());
break;
case DiscoveryStatus.LookingForDeviceAtAddress:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToDetermineDevice").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
+ StatusText = Resources.Resources.GetString("Status_AttemptingToDetermineDevice").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
break;
case DiscoveryStatus.DeviceIdentified:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToIdentifyDevice").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
+ StatusText = Resources.Resources.GetString("Status_AttemptingToIdentifyDevice").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
break;
case DiscoveryStatus.CapabilitiesDiscovered:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToGetCapabilities").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
+ StatusText = Resources.Resources.GetString("Status_AttemptingToGetCapabilities").Replace("{0}", current.Connection.BaudRate.ToString()).Replace("{1}", current.Address.ToString());
break;
case DiscoveryStatus.Succeeded:
@@ -258,18 +257,18 @@ private void UpdateDiscoveryStatus(DiscoveryResult current)
break;
case DiscoveryStatus.DeviceNotFound:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_FailedToConnect");
+ StatusText = Resources.Resources.GetString("Status_FailedToConnect");
StatusLevel = StatusLevel.Error;
break;
case DiscoveryStatus.Error:
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_ErrorWhileDiscovering");
+ StatusText = Resources.Resources.GetString("Status_ErrorWhileDiscovering");
StatusLevel = StatusLevel.Error;
break;
case DiscoveryStatus.Cancelled:
StatusLevel = StatusLevel.Error;
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_CancelledDiscovery");
+ StatusText = Resources.Resources.GetString("Status_CancelledDiscovery");
break;
default:
@@ -279,7 +278,7 @@ private void UpdateDiscoveryStatus(DiscoveryResult current)
private void HandleSuccessfulDiscovery(DiscoveryResult result)
{
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_SuccessfullyDiscovered").Replace("{0}", result.Connection.BaudRate.ToString()).Replace("{1}", result.Address.ToString());
+ StatusText = Resources.Resources.GetString("Status_SuccessfullyDiscovered").Replace("{0}", result.Connection.BaudRate.ToString()).Replace("{1}", result.Address.ToString());
StatusLevel = StatusLevel.Discovered;
if (result.Connection is ISerialPortConnectionService service)
@@ -298,7 +297,7 @@ private async Task ConnectDevice()
string serialPortName = SelectedSerialPort?.Name ?? string.Empty;
StatusLevel = StatusLevel.ConnectingManually;
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_AttemptingToConnectManually");
+ StatusText = Resources.Resources.GetString("Status_AttemptingToConnectManually");
byte[]? securityKey = await GetSecurityKey();
if (securityKey == null && !UseDefaultKey) return;
@@ -317,8 +316,8 @@ private async Task ConnectDevice()
catch (Exception exception)
{
await _dialogService.ShowMessageDialog(
- OSDPBench.Core.Resources.Resources.GetString("Dialog_Connect_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_InvalidSecurityKeyMessage").Replace("{0}", exception.Message),
+ Resources.Resources.GetString("Dialog_Connect_Title"),
+ Resources.Resources.GetString("Dialog_InvalidSecurityKeyMessage").Replace("{0}", exception.Message),
MessageIcon.Error);
return null;
}
@@ -343,7 +342,7 @@ await _deviceManagementService.Connect(
private async Task DisconnectDevice()
{
await _deviceManagementService.Shutdown();
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_Disconnected");
+ StatusText = Resources.Resources.GetString("Status_Disconnected");
StatusLevel = StatusLevel.Disconnected;
NakText = string.Empty;
_lastPacketEntry = null;
@@ -351,7 +350,7 @@ private async Task DisconnectDevice()
LastRxActiveTime = DateTime.MinValue;
}
- private async void OnUsbDeviceChanged(object? sender, UsbDeviceChangedEventArgs e)
+ private async void OnUsbDeviceChanged(object? sender, UsbDeviceChangedEventArgs eventArgs)
{
try
{
@@ -367,20 +366,13 @@ private async void OnUsbDeviceChanged(object? sender, UsbDeviceChangedEventArgs
AvailableSerialPorts.Add(port);
}
- // Handle port selection based on change type
if (AvailableSerialPorts.Count > 0)
{
// Try to reselect the previously selected port if it still exists
var previousPort = AvailableSerialPorts.FirstOrDefault(p => p.Name == currentlySelectedPort);
- if (previousPort != null)
- {
- SelectedSerialPort = previousPort;
- }
- else
- {
- // Select the first available port
- SelectedSerialPort = AvailableSerialPorts.First();
- }
+ SelectedSerialPort = previousPort ??
+ // Select the first available port
+ AvailableSerialPorts.First();
if (StatusLevel == StatusLevel.NotReady)
{
@@ -395,28 +387,28 @@ private async void OnUsbDeviceChanged(object? sender, UsbDeviceChangedEventArgs
StatusLevel = StatusLevel.NotReady;
}
}
-
- // Show notification based on change type
- if (e.ChangeType == UsbDeviceChangeType.Connected)
- {
- UsbStatusText = OSDPBench.Core.Resources.Resources.GetString("USB_DeviceConnected");
- }
- else if (e.ChangeType == UsbDeviceChangeType.Disconnected)
+
+ switch (eventArgs.ChangeType)
{
- UsbStatusText = OSDPBench.Core.Resources.Resources.GetString("USB_DeviceDisconnected");
-
- // If we were connected and the device was removed, update status
- if (StatusLevel == StatusLevel.Connected && !e.AvailablePorts.Contains(_deviceManagementService.PortName ?? ""))
+ // Show notification based on the change type
+ case UsbDeviceChangeType.Connected:
+ UsbStatusText = Resources.Resources.GetString("USB_DeviceConnected");
+ break;
+ case UsbDeviceChangeType.Disconnected:
{
- await _deviceManagementService.Shutdown();
- StatusLevel = StatusLevel.Disconnected;
- StatusText = OSDPBench.Core.Resources.Resources.GetString("Status_DeviceDisconnectedUSBRemoved");
+ UsbStatusText = Resources.Resources.GetString("USB_DeviceDisconnected");
+
+ // If we were connected and the device was removed, update status
+ if (StatusLevel == StatusLevel.Connected && !eventArgs.AvailablePorts.Contains(_deviceManagementService.PortName ?? ""))
+ {
+ await _deviceManagementService.Shutdown();
+ StatusLevel = StatusLevel.Disconnected;
+ StatusText = Resources.Resources.GetString("Status_DeviceDisconnectedUSBRemoved");
+ }
+
+ break;
}
}
- else
- {
- UsbStatusText = OSDPBench.Core.Resources.Resources.GetString("USB_PortsChanged");
- }
// Clear USB status after 3 seconds
_usbStatusTimer?.Dispose();
@@ -424,7 +416,7 @@ private async void OnUsbDeviceChanged(object? sender, UsbDeviceChangedEventArgs
}
catch (Exception ex)
{
- Console.WriteLine(OSDPBench.Core.Resources.Resources.GetString("Error_HandlingUSBDeviceChange").Replace("{0}", ex.Message));
+ Console.WriteLine(Resources.Resources.GetString("Error_HandlingUSBDeviceChange").Replace("{0}", ex.Message));
}
}
diff --git a/src/Core/ViewModels/Pages/ManageViewModel.cs b/src/Core/ViewModels/Pages/ManageViewModel.cs
index 3148582..79b230f 100644
--- a/src/Core/ViewModels/Pages/ManageViewModel.cs
+++ b/src/Core/ViewModels/Pages/ManageViewModel.cs
@@ -5,7 +5,6 @@
using OSDPBench.Core.Actions;
using OSDPBench.Core.Models;
using OSDPBench.Core.Services;
-using OSDPBench.Core.Resources;
namespace OSDPBench.Core.ViewModels.Pages;
@@ -52,7 +51,7 @@ private async Task ExecuteDeviceAction()
{
if (SelectedDeviceAction == null) return;
- await ExceptionHelper.ExecuteSafelyAsync(_dialogService, OSDPBench.Core.Resources.Resources.GetString("Dialog_PerformingAction_Title"), async () =>
+ await ExceptionHelper.ExecuteSafelyAsync(_dialogService, Resources.Resources.GetString("Dialog_PerformingAction_Title"), async () =>
{
if (SelectedDeviceAction is ResetCypressDeviceAction)
{
@@ -72,7 +71,7 @@ await ExceptionHelper.ExecuteSafelyAsync(_dialogService, OSDPBench.Core.Resource
{
return await ExceptionHelper.ExecuteSafelyAsync(
_dialogService,
- OSDPBench.Core.Resources.Resources.GetString("Dialog_PerformingAction_Title"),
+ Resources.Resources.GetString("Dialog_PerformingAction_Title"),
async () => await _deviceManagementService.ExecuteDeviceAction(SelectedDeviceAction!, DeviceActionParameter),
null);
}
@@ -87,13 +86,13 @@ private async Task HandleSetCommunicationAction(object result)
if (!parametersChanged)
{
- await _dialogService.ShowMessageDialog(OSDPBench.Core.Resources.Resources.GetString("Dialog_UpdateCommunications_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_UpdateCommunications_NoChange"), MessageIcon.Warning);
+ await _dialogService.ShowMessageDialog(Resources.Resources.GetString("Dialog_UpdateCommunications_Title"),
+ Resources.Resources.GetString("Dialog_UpdateCommunications_NoChange"), MessageIcon.Warning);
return;
}
- await _dialogService.ShowMessageDialog(OSDPBench.Core.Resources.Resources.GetString("Dialog_UpdateCommunications_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_UpdateCommunications_Success"), MessageIcon.Information);
+ await _dialogService.ShowMessageDialog(Resources.Resources.GetString("Dialog_UpdateCommunications_Title"),
+ Resources.Resources.GetString("Dialog_UpdateCommunications_Success"), MessageIcon.Information);
if (_deviceManagementService.PortName != null)
{ await _deviceManagementService.Reconnect(_serialPortConnectionService.GetConnection(
@@ -109,7 +108,7 @@ private async Task HandleResetCypressDeviceAction()
if (!IdentityLookup.CanSendResetCommand)
{
await _dialogService.ShowMessageDialog(
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Title"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Title"),
IdentityLookup.ResetInstructions,
MessageIcon.Information);
return;
@@ -118,8 +117,8 @@ await _dialogService.ShowMessageDialog(
await _deviceManagementService.Shutdown();
bool userConfirmed = await _dialogService.ShowConfirmationDialog(
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Confirmation"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Title"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Confirmation"),
MessageIcon.Warning);
if (!userConfirmed)
@@ -134,7 +133,7 @@ await _deviceManagementService.Reconnect(_serialPortConnectionService.GetConnect
return;
}
- bool success = await ExceptionHelper.ExecuteSafelyAsync(_dialogService, OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Title"), async () =>
+ bool success = await ExceptionHelper.ExecuteSafelyAsync(_dialogService, Resources.Resources.GetString("Dialog_ResetDevice_Title"), async () =>
{
if (_deviceManagementService.PortName != null)
{
@@ -149,15 +148,15 @@ await _deviceManagementService.ExecuteDeviceAction(
if (success)
{
await _dialogService.ShowMessageDialog(
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Success"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Title"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Success"),
MessageIcon.Information);
}
else
{
await _dialogService.ShowMessageDialog(
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Title"),
- OSDPBench.Core.Resources.Resources.GetString("Dialog_ResetDevice_Failed"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Title"),
+ Resources.Resources.GetString("Dialog_ResetDevice_Failed"),
MessageIcon.Error);
}
}
diff --git a/src/Core/ViewModels/Windows/MainWindowViewModel.cs b/src/Core/ViewModels/Windows/MainWindowViewModel.cs
index e701e51..d747feb 100644
--- a/src/Core/ViewModels/Windows/MainWindowViewModel.cs
+++ b/src/Core/ViewModels/Windows/MainWindowViewModel.cs
@@ -6,7 +6,7 @@ namespace OSDPBench.Core.ViewModels.Windows;
///
/// Represents the view model for the main window of the application.
///
-public partial class MainWindowViewModel : ObservableObject
+public class MainWindowViewModel : ObservableObject
{
///
/// Gets the language selection view model
diff --git a/src/UI/UsbSerialForAndroid/.gitattributes b/src/UI/UsbSerialForAndroid/.gitattributes
deleted file mode 100644
index 1ff0c42..0000000
--- a/src/UI/UsbSerialForAndroid/.gitattributes
+++ /dev/null
@@ -1,63 +0,0 @@
-###############################################################################
-# Set default behavior to automatically normalize line endings.
-###############################################################################
-* text=auto
-
-###############################################################################
-# Set default behavior for command prompt diff.
-#
-# This is need for earlier builds of msysgit that does not have it on by
-# default for csharp files.
-# Note: This is only used by command line
-###############################################################################
-#*.cs diff=csharp
-
-###############################################################################
-# Set the merge driver for project and solution files
-#
-# Merging from the command prompt will add diff markers to the files if there
-# are conflicts (Merging from VS is not affected by the settings below, in VS
-# the diff markers are never inserted). Diff markers may cause the following
-# file extensions to fail to load in VS. An alternative would be to treat
-# these files as binary and thus will always conflict and require user
-# intervention with every merge. To do so, just uncomment the entries below
-###############################################################################
-#*.sln merge=binary
-#*.csproj merge=binary
-#*.vbproj merge=binary
-#*.vcxproj merge=binary
-#*.vcproj merge=binary
-#*.dbproj merge=binary
-#*.fsproj merge=binary
-#*.lsproj merge=binary
-#*.wixproj merge=binary
-#*.modelproj merge=binary
-#*.sqlproj merge=binary
-#*.wwaproj merge=binary
-
-###############################################################################
-# behavior for image files
-#
-# image files are treated as binary by default.
-###############################################################################
-#*.jpg binary
-#*.png binary
-#*.gif binary
-
-###############################################################################
-# diff behavior for common document formats
-#
-# Convert binary document formats to text before diffing them. This feature
-# is only available from the command line. Turn it on by uncommenting the
-# entries below.
-###############################################################################
-#*.doc diff=astextplain
-#*.DOC diff=astextplain
-#*.docx diff=astextplain
-#*.DOCX diff=astextplain
-#*.dot diff=astextplain
-#*.DOT diff=astextplain
-#*.pdf diff=astextplain
-#*.PDF diff=astextplain
-#*.rtf diff=astextplain
-#*.RTF diff=astextplain
diff --git a/src/UI/UsbSerialForAndroid/.gitignore b/src/UI/UsbSerialForAndroid/.gitignore
deleted file mode 100644
index 84a4cfa..0000000
--- a/src/UI/UsbSerialForAndroid/.gitignore
+++ /dev/null
@@ -1,248 +0,0 @@
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-[Xx]64/
-[Xx]86/
-[Bb]uild/
-bld/
-[Bb]in/
-[Oo]bj/
-
-# Visual Studio 2015 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# DNX
-project.lock.json
-artifacts/
-
-*_i.c
-*_p.c
-*_i.h
-*.ilk
-*.meta
-*.obj
-*.pch
-*.pdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-
-# TODO: Un-comment the next line if you do not want to checkin
-# your web deploy settings because they may include unencrypted
-# passwords
-#*.pubxml
-*.publishproj
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/packages/*
-# except build/, which is used as an MSBuild target.
-!**/packages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/packages/repositories.config
-# NuGet v3's project.json files produces more ignoreable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Microsoft Azure ApplicationInsights config file
-ApplicationInsights.config
-
-# Windows Store app package directory
-AppPackages/
-BundleArtifacts/
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-[Ss]tyle[Cc]op.*
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.pfx
-*.publishsettings
-node_modules/
-orleans.codegen.cs
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-
-# SQL Server files
-*.mdf
-*.ldf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# LightSwitch generated files
-GeneratedArtifacts/
-ModelManifest.xml
-
-# Paket dependency manager
-.paket/paket.exe
-
-# FAKE - F# Make
-.fake/
-
-#Zip files
-*.zip
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/LICENSE.txt b/src/UI/UsbSerialForAndroid/LICENSE.txt
deleted file mode 100644
index c5e6b6b..0000000
--- a/src/UI/UsbSerialForAndroid/LICENSE.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-MIT License
-
-Copyright (c) 2011-2017 Google Inc.
-Copyright (c) 2017 Tyler Technologies
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/README.md b/src/UI/UsbSerialForAndroid/README.md
deleted file mode 100644
index 1780d36..0000000
--- a/src/UI/UsbSerialForAndroid/README.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# UsbSerialForAndroid
-
-[](https://chrismillercode.visualstudio.com/UsbSerialForAndroid/_build/latest?definitionId=1&branchName=master)
-
-This is a driver library to allow your Xamarin Android app to communicate with many common USB serial hardware. It uses the [Android USB Host API](http://developer.android.com/guide/topics/connectivity/usb/host.html)
-available on Android 3.1+.
-
-No root access, ADK, or special kernel drivers are required; all drivers are implemented in
-c#. You get a raw serial port with `Read()`, `Write()`, and other basic
-functions for use with your own protocols. The appropriate driver is picked based on the device's Vendor ID and Product ID.
-
-This is a Xamarin C# port of Mike Wakerly's Java [usb-serial-for-android](https://github.com/mik3y/usb-serial-for-android) library. It followed that library very closely when it was ported. The main changes were to make the method names follow C# standard naming conventions. Some Java specific data types were replaced with .NET types and the reflection code is .NET specific. Code examples written for the Java version of the library should translate more or less faithfully to C#.
-
-It also includes code derived from a portion of LusoVU's [XamarinUsbSerial](https://bitbucket.org/lusovu/xamarinusbserial) library. XamarinUsbSerial was a C# wrapper for the Java usb-serial-for-android. It used an older version of the usb-serial-for-android .jar file. Only the the C# code was used, the Java library is not referenced.
-
-The default branch has been renamed from master to main. if you have a local clone, you can run the following commands to update the name of the default branch
-
-```
-git branch -m master main
-git fetch origin
-git branch -u origin/main main
-git remote set-head origin -a
-```
-
-## Structure
-
-This solution contains two projects.
-
-* UsbSerialForAndroid - A port of the Java library usb-serial-for-android
-* UsbSerialExampleApp - A Xamarin version of the example app that comes with usb-serial-for-android
-
-## Getting Started
-**1.** Reference the library to your project
-
-**2.** Copy the [device_filter.axml](https://github.com/anotherlab/UsbSerialForAndroid/blob/master/UsbSerialExampleApp/Resources/xml/device_filter.xml) from the example app to your Resources/xml folder. Make sure that the Build Action is set to AndroidResource
-
-**3.** Add the following attribute to the main activity to enable the USB Host
-```C#
-[assembly: UsesFeature("android.hardware.usb.host")]
-```
-
-**4.** Add the following IntentFilter to the main activity to receive USB device attached notifications
-```C#
-[IntentFilter(new[] { UsbManager.ActionUsbDeviceAttached })]
-```
-
-**5.** Add the MetaData attribute to associate the device_filter with the USB attached event to only see the devices that we are looking for
-```C#
-[MetaData(UsbManager.ActionUsbDeviceAttached, Resource = "@xml/device_filter")]
-```
-
-**6.** Refer to [MainActivity.cs](https://github.com/anotherlab/UsbSerialForAndroid/blob/master/UsbSerialExampleApp/MainActivity.cs) in the example app to see how connect to a serial device and read data from it.
-
-## Working with unrecognized devices
-The UsbSerialForAndroid has been compiled with the Vendor ID/Product ID pairs for many common serial devices. If you have a device that is not defined by the library, but will work with one of the drivers, you can manually add the VID/PID pair.
-
-UsbSerialProber is a class to help you find and instantiate compatible
-UsbSerialDrivers from the tree of connected UsbDevices. Normally, you will use
-the default prober returned by ``UsbSerialProber.getDefaultProber()``, which
-uses the built-in list of well-known VIDs and PIDs that are supported by our
-drivers.
-
-To use your own set of rules, create and use a custom prober:
-
-```C#
-// Probe for our custom CDC devices, which use VID 0x1234
-// and PIDS 0x0001 and 0x0002.
-var table = UsbSerialProber.DefaultProbeTable;
-table.AddProduct(0x1b4f, 0x0008, typeof(CdcAcmSerialDriver)); // IOIO OTG
-
-table.AddProduct(0x09D8, 0x0420, typeof(CdcAcmSerialDriver)); // Elatec TWN4
-
-var prober = new UsbSerialProber(table);
-List drivers = prober.FindAllDrivers(usbManager);
-// ...
-```
-
-Of course, nothing requires you to use UsbSerialProber at all: you can
-instantiate driver classes directly if you know what you're doing; just supply
-a compatible UsbDevice.
-
-
-## Compatible Devices
-
-* *Serial chips:* FT232R, CDC/ACM (eg Arduino Uno) and possibly others.
- See [CompatibleSerialDevices](https://github.com/mik3y/usb-serial-for-android/wiki/Compatible-Serial-Devices).
-* *Android phones and tablets:* Nexus 7, Motorola Xoom, and many others.
- See [CompatibleAndroidDevices](https://github.com/mik3y/usb-serial-for-android/wiki/Compatible-Android-Devices).
-
-## Additional information
-
-This is a port of the usb-serial-for-android library and code examples written for it can be adapted to C# without much effort.
-
-For common problems, see the
-[Troubleshooting](https://github.com/mik3y/usb-serial-for-android/wiki/Troubleshooting)
-wiki page for usb-serial-for-android library.
-
-For other help and discussion, please join the usb-serial-for-android Google Group,
-[usb-serial-for-android](https://groups.google.com/forum/?fromgroups#!forum/usb-serial-for-android).
-
-Pull Requests are welcome, but please include what hardware was used for testing. I do not have the hardware or the bandwidth to test the various chipsets supported by the library.
-
-## Author, License, and Copyright
-
-This library is licensed under LGPL Version 2.1. Please see LICENSE.txt for the complete license.
-
-Copyright 2017, Tyler Technologies. All Rights Reserved. Portions of this library are based on the [usb-serial-for-android](https://github.com/mik3y/usb-serial-for-android) and [XamarinUsbSerial](https://bitbucket.org/lusovu/xamarinusbserial) libraries. Their rights remain intact.
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Assets/AboutAssets.txt b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Assets/AboutAssets.txt
deleted file mode 100644
index ee39886..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Assets/AboutAssets.txt
+++ /dev/null
@@ -1,19 +0,0 @@
-Any raw assets you want to be deployed with your application can be placed in
-this directory (and child directories) and given a Build Action of "AndroidAsset".
-
-These files will be deployed with you package and will be accessible using Android's
-AssetManager, like this:
-
-public class ReadAsset : Activity
-{
- protected override void OnCreate (Bundle bundle)
- {
- base.OnCreate (bundle);
-
- InputStream input = Assets.Open ("my_asset.txt");
- }
-}
-
-Additionally, some Android functions will automatically load asset files:
-
-Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/GettingStarted.Xamarin b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/GettingStarted.Xamarin
deleted file mode 100644
index e9d4f6a..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/GettingStarted.Xamarin
+++ /dev/null
@@ -1,4 +0,0 @@
-
- GS\Android\CS\AndroidApp\GettingStarted.html
- false
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/MainActivity.cs b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/MainActivity.cs
deleted file mode 100644
index 3c6f148..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/MainActivity.cs
+++ /dev/null
@@ -1,222 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Android.App;
-using Android.Content;
-using Android.Hardware.Usb;
-using Android.Runtime;
-using Android.Views;
-using Android.Widget;
-using Android.OS;
-using Android.Util;
-using Hoho.Android.UsbSerial.Driver;
-using Hoho.Android.UsbSerial.Extensions;
-using Hoho.Android.UsbSerial.Util;
-
-
-[assembly: UsesFeature("android.hardware.usb.host")]
-
-
-namespace UsbSerialExampleApp
-{
- [Activity(Label = "UsbSerialExampleApp", MainLauncher = true, Icon = "@drawable/icon")]
- [IntentFilter(new[] { UsbManager.ActionUsbDeviceAttached })]
- [MetaData(UsbManager.ActionUsbDeviceAttached, Resource = "@xml/device_filter")]
- public class MainActivity : Activity
- {
- static readonly string TAG = typeof(MainActivity).Name;
- const string ACTION_USB_PERMISSION = "com.hoho.android.usbserial.examples.USB_PERMISSION";
-
- UsbManager usbManager;
- ListView listView;
- TextView progressBarTitle;
- ProgressBar progressBar;
-
- UsbSerialPortAdapter adapter;
- BroadcastReceiver detachedReceiver;
- UsbSerialPort selectedPort;
-
-
- protected override void OnCreate(Bundle bundle)
- {
- base.OnCreate(bundle);
-
- // Set our view from the "main" layout resource
- SetContentView(Resource.Layout.Main);
-
- usbManager = GetSystemService(Context.UsbService) as UsbManager;
- listView = FindViewById(Resource.Id.deviceList);
- progressBar = FindViewById(Resource.Id.progressBar);
- progressBarTitle = FindViewById(Resource.Id.progressBarTitle);
- }
-
- protected override async void OnResume()
- {
- base.OnResume();
-
- adapter = new UsbSerialPortAdapter(this);
- listView.Adapter = adapter;
-
- listView.ItemClick += async (sender, e) => {
- await OnItemClick(sender, e);
- };
-
- await PopulateListAsync();
-
- //register the broadcast receivers
- detachedReceiver = new UsbDeviceDetachedReceiver(this);
- RegisterReceiver(detachedReceiver, new IntentFilter(UsbManager.ActionUsbDeviceDetached));
- }
- protected override void OnPause()
- {
- base.OnPause();
-
- // unregister the broadcast receivers
- var temp = detachedReceiver; // copy reference for thread safety
- if (temp != null)
- UnregisterReceiver(temp);
- }
- internal static Task> FindAllDriversAsync(UsbManager usbManager)
- {
- // using the default probe table
- // return UsbSerialProber.DefaultProber.FindAllDriversAsync (usbManager);
-
- // adding a custom driver to the default probe table
- var table = UsbSerialProber.DefaultProbeTable;
- table.AddProduct(0x1b4f, 0x0008, typeof(CdcAcmSerialDriver)); // IOIO OTG
-
- table.AddProduct(0x09D8, 0x0420, typeof(CdcAcmSerialDriver)); // Elatec TWN4
-
- var prober = new UsbSerialProber(table);
- return prober.FindAllDriversAsync(usbManager);
- }
-
- async Task OnItemClick(object sender, AdapterView.ItemClickEventArgs e)
- {
- Log.Info(TAG, "Pressed item " + e.Position);
- if (e.Position >= adapter.Count)
- {
- Log.Info(TAG, "Illegal position.");
- return;
- }
-
- // request user permission to connect to device
- // NOTE: no request is shown to user if permission already granted
- selectedPort = adapter.GetItem(e.Position);
- var permissionGranted = await usbManager.RequestPermissionAsync(selectedPort.Driver.Device, this);
- if (permissionGranted)
- {
- // start the SerialConsoleActivity for this device
- var newIntent = new Intent(this, typeof(SerialConsoleActivity));
- newIntent.PutExtra(SerialConsoleActivity.EXTRA_TAG, new UsbSerialPortInfo(selectedPort));
- StartActivity(newIntent);
- }
- }
-
- async Task PopulateListAsync()
- {
- ShowProgressBar();
-
- Log.Info(TAG, "Refreshing device list ...");
-
- var drivers = await FindAllDriversAsync(usbManager);
-
- adapter.Clear();
- foreach (var driver in drivers)
- {
- var ports = driver.Ports;
- Log.Info(TAG, string.Format("+ {0}: {1} port{2}", driver, ports.Count, ports.Count == 1 ? string.Empty : "s"));
- foreach (var port in ports)
- adapter.Add(port);
- }
-
- adapter.NotifyDataSetChanged();
- progressBarTitle.Text = string.Format("{0} device{1} found", adapter.Count, adapter.Count == 1 ? string.Empty : "s");
- HideProgressBar();
- Log.Info(TAG, "Done refreshing, " + adapter.Count + " entries found.");
- }
-
- void ShowProgressBar()
- {
- progressBar.Visibility = ViewStates.Visible;
- progressBarTitle.Text = GetString(Resource.String.refreshing);
- }
-
- void HideProgressBar()
- {
- progressBar.Visibility = ViewStates.Invisible;
- }
-
-
- #region UsbSerialPortAdapter implementation
-
- class UsbSerialPortAdapter : ArrayAdapter
- {
- public UsbSerialPortAdapter(Context context)
- : base(context, global::Android.Resource.Layout.SimpleExpandableListItem2)
- {
- }
-
- public override View GetView(int position, View convertView, ViewGroup parent)
- {
- var row = convertView;
- if (row == null)
- {
- var inflater = Context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
- row = inflater.Inflate(global::Android.Resource.Layout.SimpleListItem2, null);
- }
-
- var port = this.GetItem(position);
- var driver = port.GetDriver();
- var device = driver.GetDevice();
-
- var title = string.Format("Vendor {0} Product {1}",
- HexDump.ToHexString((short)device.VendorId),
- HexDump.ToHexString((short)device.ProductId));
- row.FindViewById(global::Android.Resource.Id.Text1).Text = title;
-
- var subtitle = device.Class.SimpleName;
- row.FindViewById(global::Android.Resource.Id.Text2).Text = subtitle;
-
- return row;
- }
- }
-
- #endregion
-
- #region UsbDeviceDetachedReceiver implementation
-
- class UsbDeviceDetachedReceiver
- : BroadcastReceiver
- {
- readonly string TAG = typeof(UsbDeviceDetachedReceiver).Name;
- readonly MainActivity activity;
-
- public UsbDeviceDetachedReceiver(MainActivity activity)
- {
- this.activity = activity;
- }
-
- public async override void OnReceive(Context context, Intent intent)
- {
- var device = intent.GetParcelableExtra(UsbManager.ExtraDevice) as UsbDevice;
-
- Log.Info(TAG, "USB device detached: " + device.DeviceName);
-
- await activity.PopulateListAsync();
- }
- }
-
- #endregion
-
-
- }
-}
-
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AndroidManifest.xml b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AndroidManifest.xml
deleted file mode 100644
index 2fc30a2..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AndroidManifest.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AssemblyInfo.cs b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AssemblyInfo.cs
deleted file mode 100644
index ba38bad..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,30 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using Android.App;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("UsbSerialExampleApp")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("UsbSerialExampleApp")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/AboutResources.txt b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/AboutResources.txt
deleted file mode 100644
index c2bca97..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/AboutResources.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-Images, layout descriptions, binary blobs and string dictionaries can be included
-in your application as resource files. Various Android APIs are designed to
-operate on the resource IDs instead of dealing with images, strings or binary blobs
-directly.
-
-For example, a sample Android app that contains a user interface layout (main.axml),
-an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
-would keep its resources in the "Resources" directory of the application:
-
-Resources/
- drawable/
- icon.png
-
- layout/
- main.axml
-
- values/
- strings.xml
-
-In order to get the build system to recognize Android resources, set the build action to
-"AndroidResource". The native Android APIs do not operate directly with filenames, but
-instead operate on resource IDs. When you compile an Android application that uses resources,
-the build system will package the resources for distribution and generate a class called "R"
-(this is an Android convention) that contains the tokens for each one of the resources
-included. For example, for the above Resources layout, this is what the R class would expose:
-
-public class R {
- public class drawable {
- public const int icon = 0x123;
- }
-
- public class layout {
- public const int main = 0x456;
- }
-
- public class strings {
- public const int first_string = 0xabc;
- public const int second_string = 0xbcd;
- }
-}
-
-You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
-to reference the layout/main.axml file, or R.strings.first_string to reference the first
-string in the dictionary file values/strings.xml.
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/Resource.Designer.cs b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/Resource.Designer.cs
deleted file mode 100644
index 696074e..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/Resource.Designer.cs
+++ /dev/null
@@ -1,169 +0,0 @@
-#pragma warning disable 1591
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-[assembly: global::Android.Runtime.ResourceDesignerAttribute("UsbSerialExampleApp.Resource", IsApplication=true)]
-
-namespace UsbSerialExampleApp
-{
-
-
- [System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
- public partial class Resource
- {
-
- static Resource()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- public static void UpdateIdValues()
- {
- global::Hoho.Android.UsbSerial.Resource.String.ApplicationName = global::UsbSerialExampleApp.Resource.String.ApplicationName;
- global::Hoho.Android.UsbSerial.Resource.String.Hello = global::UsbSerialExampleApp.Resource.String.Hello;
- }
-
- public partial class Attribute
- {
-
- static Attribute()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Attribute()
- {
- }
- }
-
- public partial class Drawable
- {
-
- // aapt resource value: 0x7f020000
- public const int Icon = 2130837504;
-
- static Drawable()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Drawable()
- {
- }
- }
-
- public partial class Id
- {
-
- // aapt resource value: 0x7f060008
- public const int consoleText = 2131099656;
-
- // aapt resource value: 0x7f060007
- public const int demoScroller = 2131099655;
-
- // aapt resource value: 0x7f060001
- public const int demoTitle = 2131099649;
-
- // aapt resource value: 0x7f060004
- public const int deviceList = 2131099652;
-
- // aapt resource value: 0x7f060002
- public const int progressBar = 2131099650;
-
- // aapt resource value: 0x7f060000
- public const int progressBarTitle = 2131099648;
-
- // aapt resource value: 0x7f060003
- public const int separator = 2131099651;
-
- // aapt resource value: 0x7f060005
- public const int sleepButton = 2131099653;
-
- // aapt resource value: 0x7f060006
- public const int wakeupButton = 2131099654;
-
- static Id()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Id()
- {
- }
- }
-
- public partial class Layout
- {
-
- // aapt resource value: 0x7f030000
- public const int Main = 2130903040;
-
- // aapt resource value: 0x7f030001
- public const int serial_console = 2130903041;
-
- static Layout()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Layout()
- {
- }
- }
-
- public partial class String
- {
-
- // aapt resource value: 0x7f050001
- public const int ApplicationName = 2131034113;
-
- // aapt resource value: 0x7f050000
- public const int Hello = 2131034112;
-
- // aapt resource value: 0x7f050002
- public const int app_name = 2131034114;
-
- // aapt resource value: 0x7f050003
- public const int refreshing = 2131034115;
-
- // aapt resource value: 0x7f050004
- public const int sleep = 2131034116;
-
- // aapt resource value: 0x7f050005
- public const int wakeup = 2131034117;
-
- static String()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private String()
- {
- }
- }
-
- public partial class Xml
- {
-
- // aapt resource value: 0x7f040000
- public const int device_filter = 2130968576;
-
- static Xml()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Xml()
- {
- }
- }
- }
-}
-#pragma warning restore 1591
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/drawable/Icon.png b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/drawable/Icon.png
deleted file mode 100644
index 8074c4c..0000000
Binary files a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/drawable/Icon.png and /dev/null differ
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/Main.axml b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/Main.axml
deleted file mode 100644
index 683e784..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/Main.axml
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/serial_console.axml b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/serial_console.axml
deleted file mode 100644
index f97b0de..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/layout/serial_console.axml
+++ /dev/null
@@ -1,44 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/values/Strings.xml b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/values/Strings.xml
deleted file mode 100644
index cfb4418..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/values/Strings.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
- USB Serial Example
- Refreshing...
- Sleep
- Wakeup
-
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/xml/device_filter.xml b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/xml/device_filter.xml
deleted file mode 100644
index c0b405b..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/Resources/xml/device_filter.xml
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/SerialConsoleActivity.cs b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/SerialConsoleActivity.cs
deleted file mode 100644
index e9e6fb2..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/SerialConsoleActivity.cs
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-
-using Android.App;
-using Android.Content;
-using Android.Content.PM;
-using Android.Hardware.Usb;
-using Android.OS;
-using Android.Runtime;
-using Android.Util;
-using Android.Views;
-using Android.Widget;
-
-using Hoho.Android.UsbSerial.Driver;
-using Hoho.Android.UsbSerial.Extensions;
-using Hoho.Android.UsbSerial.Util;
-
-
-namespace UsbSerialExampleApp
-{
- [Activity(Label = "@string/app_name", LaunchMode = LaunchMode.SingleTop)]
- public class SerialConsoleActivity : Activity
- {
- static readonly string TAG = typeof(SerialConsoleActivity).Name;
-
- public const string EXTRA_TAG = "PortInfo";
- const int READ_WAIT_MILLIS = 200;
- const int WRITE_WAIT_MILLIS = 200;
-
- UsbSerialPort port;
-
- UsbManager usbManager;
- TextView titleTextView;
- TextView dumpTextView;
- ScrollView scrollView;
- Button sleepButton;
- Button wakeButton;
-
- SerialInputOutputManager serialIoManager;
-
- protected override void OnCreate(Bundle savedInstanceState)
- {
- Log.Info(TAG, "OnCreate");
-
- base.OnCreate(savedInstanceState);
-
- SetContentView(Resource.Layout.serial_console);
-
- usbManager = GetSystemService(Context.UsbService) as UsbManager;
- titleTextView = FindViewById(Resource.Id.demoTitle);
- dumpTextView = FindViewById(Resource.Id.consoleText);
- scrollView = FindViewById(Resource.Id.demoScroller);
-
- sleepButton = FindViewById(Resource.Id.sleepButton);
- wakeButton = FindViewById(Resource.Id.wakeupButton);
-
- // The following arrays contain data that is used for a custom firmware for
- // the Elatec TWN4 RFID reader. This code is included here to show how to
- // send data back to a USB serial device
- byte[] sleepdata = new byte[] { 0xf0, 0x04, 0x10, 0xf1 };
- byte[] wakedata = new byte[] { 0xf0, 0x04, 0x11, 0xf1 };
-
- sleepButton.Click += delegate
- {
- WriteData(sleepdata);
- };
-
- wakeButton.Click += delegate
- {
- WriteData(wakedata);
- };
- }
-
- protected override void OnPause()
- {
- Log.Info(TAG, "OnPause");
-
- base.OnPause();
-
- if (serialIoManager != null && serialIoManager.IsOpen)
- {
- Log.Info(TAG, "Stopping IO manager ..");
- try
- {
- serialIoManager.Close();
- }
- catch (Java.IO.IOException)
- {
- // ignore
- }
- }
- }
-
- protected async override void OnResume()
- {
- Log.Info(TAG, "OnResume");
-
- base.OnResume();
-
- var portInfo = Intent.GetParcelableExtra(EXTRA_TAG) as UsbSerialPortInfo;
- int vendorId = portInfo.VendorId;
- int deviceId = portInfo.DeviceId;
- int portNumber = portInfo.PortNumber;
-
- Log.Info(TAG, string.Format("VendorId: {0} DeviceId: {1} PortNumber: {2}", vendorId, deviceId, portNumber));
-
- var drivers = await MainActivity.FindAllDriversAsync(usbManager);
- var driver = drivers.Where((d) => d.Device.VendorId == vendorId && d.Device.DeviceId == deviceId).FirstOrDefault();
- if (driver == null)
- throw new Exception("Driver specified in extra tag not found.");
-
- port = driver.Ports[portNumber];
- if (port == null)
- {
- titleTextView.Text = "No serial device.";
- return;
- }
- Log.Info(TAG, "port=" + port);
-
- titleTextView.Text = "Serial device: " + port.GetType().Name;
-
- serialIoManager = new SerialInputOutputManager(port)
- {
- BaudRate = 115200,
- DataBits = 8,
- StopBits = StopBits.One,
- Parity = Parity.None,
- };
- serialIoManager.DataReceived += (sender, e) => {
- RunOnUiThread(() => {
- UpdateReceivedData(e.Data);
- });
- };
- serialIoManager.ErrorReceived += (sender, e) => {
- RunOnUiThread(() => {
- var intent = new Intent(this, typeof(MainActivity));
- StartActivity(intent);
- });
- };
-
- Log.Info(TAG, "Starting IO manager ..");
- try
- {
- serialIoManager.Open(usbManager);
- }
- catch (Java.IO.IOException e)
- {
- titleTextView.Text = "Error opening device: " + e.Message;
- return;
- }
- }
-
- void WriteData(byte[] data)
- {
- if (serialIoManager.IsOpen)
- {
- port.Write(data, WRITE_WAIT_MILLIS);
- }
- }
-
- void UpdateReceivedData(byte[] data)
- {
- var message = "Read " + data.Length + " bytes: \n"
- + HexDump.DumpHexString(data) + "\n\n";
-
- dumpTextView.Append(message);
- scrollView.SmoothScrollTo(0, dumpTextView.Bottom);
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/UsbSerialExampleApp.csproj b/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/UsbSerialExampleApp.csproj
deleted file mode 100644
index 8082317..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialExampleApp/UsbSerialExampleApp.csproj
+++ /dev/null
@@ -1,99 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Library
- Properties
- UsbSerialExampleApp
- UsbSerialExampleApp
- 512
- true
- Resources\Resource.Designer.cs
- Off
- False
- v5.1
- Properties\AndroidManifest.xml
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- True
- None
-
-
- pdbonly
- true
- true
- true
- bin\Release\
- TRACE
- prompt
- 4
- False
- SdkOnly
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Designer
-
-
-
-
- Designer
-
-
-
-
-
-
-
-
-
-
-
-
-
- {a64567bc-548a-4cb7-9f2c-ece75ee1a868}
- UsbSerialForAndroid
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid.sln b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid.sln
deleted file mode 100644
index b326eb9..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid.sln
+++ /dev/null
@@ -1,30 +0,0 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 14
-VisualStudioVersion = 14.0.25420.1
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UsbSerialForAndroid", "UsbSerialForAndroid\UsbSerialForAndroid.csproj", "{A64567BC-548A-4CB7-9F2C-ECE75EE1A868}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UsbSerialExampleApp", "UsbSerialExampleApp\UsbSerialExampleApp.csproj", "{59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {A64567BC-548A-4CB7-9F2C-ECE75EE1A868}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {A64567BC-548A-4CB7-9F2C-ECE75EE1A868}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {A64567BC-548A-4CB7-9F2C-ECE75EE1A868}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {A64567BC-548A-4CB7-9F2C-ECE75EE1A868}.Release|Any CPU.Build.0 = Release|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Debug|Any CPU.Deploy.0 = Debug|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Release|Any CPU.Build.0 = Release|Any CPU
- {59C7DFF3-4E5E-42D7-BB77-E6C4F4E74512}.Release|Any CPU.Deploy.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/AsyncExtensions.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/AsyncExtensions.cs
deleted file mode 100644
index 55bb24b..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/AsyncExtensions.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System.Collections.Generic;
-using System.Threading.Tasks;
-using Android.Hardware.Usb;
-using Hoho.Android.UsbSerial.driver;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- public static partial class AsyncExtensions
- {
- public static Task> FindAllDriversAsync(this UsbSerialProber prober, UsbManager manager)
- {
- var tcs = new TaskCompletionSource>();
-
- Task.Run(() =>
- {
- tcs.TrySetResult(prober.FindAllDrivers(manager));
- });
- return tcs.Task;
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/BufferExtensions.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/BufferExtensions.cs
deleted file mode 100644
index ca4a0df..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/BufferExtensions.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-
-using Android.Runtime;
-using Java.Nio;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- ///
- /// Work around for faulty JNI wrapping in Xamarin library. Fixes a bug
- /// where binding for Java.Nio.ByteBuffer.Get(byte[], int, int) allocates a new temporary
- /// Java byte array on every call
- /// See https://bugzilla.xamarin.com/show_bug.cgi?id=31260
- /// and http://stackoverflow.com/questions/30268400/xamarin-implementation-of-bytebuffer-get-wrong
- ///
- public static class BufferExtensions
- {
- static IntPtr _byteBufferClassRef;
- static IntPtr _byteBufferGetBii;
-
- public static ByteBuffer Get(this ByteBuffer buffer, JavaArray dst, int dstOffset, int byteCount)
- {
- if (_byteBufferClassRef == IntPtr.Zero)
- {
- _byteBufferClassRef = JNIEnv.FindClass("java/nio/ByteBuffer");
- }
- if (_byteBufferGetBii == IntPtr.Zero)
- {
- _byteBufferGetBii = JNIEnv.GetMethodID(_byteBufferClassRef, "get", "([BII)Ljava/nio/ByteBuffer;");
- }
-
- return Java.Lang.Object.GetObject(JNIEnv.CallObjectMethod(buffer.Handle, _byteBufferGetBii, new JValue[] {
- new JValue(dst),
- new JValue(dstOffset),
- new JValue(byteCount)
- }), JniHandleOwnership.TransferLocalRef);
- }
-
- public static byte[] ToByteArray(this ByteBuffer buffer)
- {
- IntPtr classHandle = JNIEnv.FindClass("java/nio/ByteBuffer");
- IntPtr methodId = JNIEnv.GetMethodID(classHandle, "array", "()[B");
- IntPtr resultHandle = JNIEnv.CallObjectMethod(buffer.Handle, methodId);
-
- byte[] result = JNIEnv.GetArray(resultHandle);
-
- JNIEnv.DeleteLocalRef(resultHandle);
-
- return result;
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/EventHandlerExtensions.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/EventHandlerExtensions.cs
deleted file mode 100644
index aa2a2f6..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/EventHandlerExtensions.cs
+++ /dev/null
@@ -1,25 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Threading;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- static class EventHandlerExtensions
- {
- public static void Raise(this EventHandler handler, object sender, EventArgs e)
- {
- Volatile.Read(ref handler)?.Invoke(sender, e);
- }
-
- public static void Raise(this EventHandler handler, object sender, T e) where T : EventArgs
- {
- Volatile.Read(ref handler)?.Invoke(sender, e);
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialDataReceivedArgs.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialDataReceivedArgs.cs
deleted file mode 100644
index 501a0ee..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialDataReceivedArgs.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- public class SerialDataReceivedArgs : EventArgs
- {
- public SerialDataReceivedArgs(byte[] data)
- {
- Data = data;
- }
-
- public byte[] Data { get; private set; }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialInputOutputManager.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialInputOutputManager.cs
deleted file mode 100644
index d6ae542..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/SerialInputOutputManager.cs
+++ /dev/null
@@ -1,166 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Threading;
-using Android.Hardware.Usb;
-using Android.Util;
-using System.Threading.Tasks;
-using Hoho.Android.UsbSerial.driver;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- public class SerialInputOutputManager : IDisposable
- {
- static readonly string TAG = typeof(SerialInputOutputManager).Name;
- const int READ_WAIT_MILLIS = 200;
- const int DEFAULT_BUFFERSIZE = 4096;
- const int DEFAULT_BAUDRATE = 9600;
- const int DEFAULT_DATABITS = 8;
- const Parity DEFAULT_PARITY = Parity.None;
- const StopBits DEFAULT_STOPBITS = StopBits.One;
-
- readonly UsbSerialPort port;
- byte[] buffer;
- CancellationTokenSource cancelationTokenSource;
- bool isOpen;
-
- public SerialInputOutputManager(UsbSerialPort port)
- {
- this.port = port;
- BaudRate = DEFAULT_BAUDRATE;
- Parity = DEFAULT_PARITY;
- DataBits = DEFAULT_DATABITS;
- StopBits = DEFAULT_STOPBITS;
- }
-
- public int BaudRate { get; set; }
-
- public Parity Parity { get; set; }
-
- public int DataBits { get; set; }
-
- public StopBits StopBits { get; set; }
-
- public event EventHandler DataReceived;
-
- public event EventHandler ErrorReceived;
-
- public void Open(UsbManager usbManager, int bufferSize = DEFAULT_BUFFERSIZE)
- {
- if (disposed)
- throw new ObjectDisposedException(GetType().Name);
- if (IsOpen)
- throw new InvalidOperationException();
-
- var connection = usbManager.OpenDevice(port.GetDriver().GetDevice());
- if (connection == null)
- throw new Java.IO.IOException("Failed to open device");
- isOpen = true;
-
- buffer = new byte[bufferSize];
- port.Open(connection);
- port.SetParameters(BaudRate, DataBits, StopBits, Parity);
-
- cancelationTokenSource = new CancellationTokenSource();
- var cancelationToken = cancelationTokenSource.Token;
- cancelationToken.Register(() => Log.Info(TAG, "Cancellation Requested"));
-
- Task.Run(() => {
- Log.Info(TAG, "Task Started!");
- try
- {
- while (true)
- {
- cancelationToken.ThrowIfCancellationRequested();
-
- Step(); // execute step
- }
- }
- catch (OperationCanceledException)
- {
- throw;
- }
- catch (Exception e)
- {
- Log.Warn(TAG, "Task ending due to exception: " + e.Message, e);
- ErrorReceived.Raise(this, new UnhandledExceptionEventArgs(e, false));
- }
- finally
- {
- port.Close();
- buffer = null;
- isOpen = false;
- Log.Info(TAG, "Task Ended!");
- }
- }, cancelationToken);
- }
-
- public void Close()
- {
- if (disposed)
- throw new ObjectDisposedException(GetType().Name);
- if (!IsOpen)
- throw new InvalidOperationException();
-
- // cancel task
- cancelationTokenSource.Cancel();
- }
-
- public bool IsOpen => isOpen;
-
- void Step()
- {
- // handle incoming data.
- var len = port.Read(buffer, READ_WAIT_MILLIS);
- if (len > 0)
- {
- Log.Debug(TAG, "Read data len=" + len);
-
- var data = new byte[len];
- Array.Copy(buffer, data, len);
- DataReceived.Raise(this, new SerialDataReceivedArgs(data));
- }
- }
-
-
- #region Dispose pattern implementation
-
- bool disposed;
-
- protected virtual void Dispose(bool disposing)
- {
- if (disposed)
- return;
-
- if (disposing && (cancelationTokenSource != null))
- {
- Close();
- }
-
- disposed = true;
- }
-
- ~SerialInputOutputManager()
- {
- Dispose(false);
- }
-
- #region IDisposable implementation
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- #endregion
-
- #endregion
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbManagerExtensions.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbManagerExtensions.cs
deleted file mode 100644
index 6b28861..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbManagerExtensions.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System.Threading.Tasks;
-using Android.App;
-using Android.Content;
-using Android.Hardware.Usb;
-using Android.OS;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- public static class UsbManagerExtensions
- {
- const string ACTION_USB_PERMISSION = "com.Hoho.Android.UsbSerial.Util.USB_PERMISSION";
-
- //static readonly Dictionary, TaskCompletionSource> taskCompletionSources =
- // new Dictionary, TaskCompletionSource>();
-
- public static Task RequestPermissionAsync(this UsbManager manager, UsbDevice device, Context context)
- {
- var completionSource = new TaskCompletionSource();
-
- var usbPermissionReceiver = new UsbPermissionReceiver(completionSource);
- context.RegisterReceiver(usbPermissionReceiver, new IntentFilter(ACTION_USB_PERMISSION));
-
- var pendingIntentFlags = Build.VERSION.SdkInt >= BuildVersionCodes.S
- ? PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Mutable
- : PendingIntentFlags.UpdateCurrent;
- var intent = PendingIntent.GetBroadcast(context, 0, new Intent(ACTION_USB_PERMISSION), pendingIntentFlags);
- manager.RequestPermission(device, intent);
-
- return completionSource.Task;
- }
-
- class UsbPermissionReceiver: BroadcastReceiver
- {
- readonly TaskCompletionSource completionSource;
-
- public UsbPermissionReceiver(TaskCompletionSource completionSource)
- {
- this.completionSource = completionSource;
- }
-
- public override void OnReceive(Context context, Intent intent)
- {
- var device = intent.GetParcelableExtra(UsbManager.ExtraDevice) as UsbDevice;
- var permissionGranted = intent.GetBooleanExtra(UsbManager.ExtraPermissionGranted, false);
- context.UnregisterReceiver(this);
- completionSource.TrySetResult(permissionGranted);
- }
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbSerialPortInfo.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbSerialPortInfo.cs
deleted file mode 100644
index d2e9ae7..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Extensions/UsbSerialPortInfo.cs
+++ /dev/null
@@ -1,86 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using Android.OS;
-using Hoho.Android.UsbSerial.driver;
-using Java.Interop;
-
-namespace Hoho.Android.UsbSerial.Extensions
-{
- public sealed class UsbSerialPortInfo : Java.Lang.Object, IParcelable
- {
- static readonly IParcelableCreator creator = new ParcelableCreator();
-
- [ExportField("CREATOR")]
- public static IParcelableCreator GetCreator()
- {
- return creator;
- }
-
- public UsbSerialPortInfo()
- {
- }
-
- public UsbSerialPortInfo(UsbSerialPort port)
- {
- var device = port.Driver.Device;
- VendorId = device.VendorId;
- DeviceId = device.DeviceId;
- PortNumber = port.PortNumber;
- }
-
- private UsbSerialPortInfo(Parcel parcel)
- {
- VendorId = parcel.ReadInt();
- DeviceId = parcel.ReadInt();
- PortNumber = parcel.ReadInt();
- }
-
- public int VendorId { get; set; }
-
- public int DeviceId { get; set; }
-
- public int PortNumber { get; set; }
-
- #region IParcelable implementation
-
- public int DescribeContents()
- {
- return 0;
- }
-
- public void WriteToParcel(Parcel dest, ParcelableWriteFlags flags)
- {
- dest.WriteInt(VendorId);
- dest.WriteInt(DeviceId);
- dest.WriteInt(PortNumber);
- }
-
- #endregion
-
- #region ParcelableCreator implementation
-
- public sealed class ParcelableCreator : Java.Lang.Object, IParcelableCreator
- {
- #region IParcelableCreator implementation
-
- public Java.Lang.Object CreateFromParcel(Parcel parcel)
- {
- return new UsbSerialPortInfo(parcel);
- }
-
- public Java.Lang.Object[] NewArray(int size)
- {
- return new UsbSerialPortInfo[size];
- }
-
- #endregion
- }
-
- #endregion
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Properties/AssemblyInfo.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Properties/AssemblyInfo.cs
deleted file mode 100644
index e06185f..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("UsbSerialForAndroid")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("UsbSerialForAndroid")]
-[assembly: AssemblyCopyright("Copyright © 2016")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: ComVisible(false)]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.4.*")]
-[assembly: AssemblyFileVersion("1.0.4.*")]
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/AboutResources.txt b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/AboutResources.txt
deleted file mode 100644
index c2bca97..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/AboutResources.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-Images, layout descriptions, binary blobs and string dictionaries can be included
-in your application as resource files. Various Android APIs are designed to
-operate on the resource IDs instead of dealing with images, strings or binary blobs
-directly.
-
-For example, a sample Android app that contains a user interface layout (main.axml),
-an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
-would keep its resources in the "Resources" directory of the application:
-
-Resources/
- drawable/
- icon.png
-
- layout/
- main.axml
-
- values/
- strings.xml
-
-In order to get the build system to recognize Android resources, set the build action to
-"AndroidResource". The native Android APIs do not operate directly with filenames, but
-instead operate on resource IDs. When you compile an Android application that uses resources,
-the build system will package the resources for distribution and generate a class called "R"
-(this is an Android convention) that contains the tokens for each one of the resources
-included. For example, for the above Resources layout, this is what the R class would expose:
-
-public class R {
- public class drawable {
- public const int icon = 0x123;
- }
-
- public class layout {
- public const int main = 0x456;
- }
-
- public class strings {
- public const int first_string = 0xabc;
- public const int second_string = 0xbcd;
- }
-}
-
-You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
-to reference the layout/main.axml file, or R.strings.first_string to reference the first
-string in the dictionary file values/strings.xml.
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Resource.Designer.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Resource.Designer.cs
deleted file mode 100644
index 28b2359..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Resource.Designer.cs
+++ /dev/null
@@ -1,59 +0,0 @@
-#pragma warning disable 1591
-//------------------------------------------------------------------------------
-//
-// This code was generated by a tool.
-//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
-//
-//------------------------------------------------------------------------------
-
-[assembly: global::Android.Runtime.ResourceDesignerAttribute("Hoho.Android.UsbSerial.Resource", IsApplication=false)]
-
-namespace Hoho.Android.UsbSerial
-{
-
-
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.2.120")]
- public partial class Resource
- {
-
- static Resource()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- public partial class Attribute
- {
-
- static Attribute()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private Attribute()
- {
- }
- }
-
- public partial class String
- {
-
- // aapt resource value: 0x7F010000
- public static int ApplicationName = 2130771968;
-
- // aapt resource value: 0x7F010001
- public static int Hello = 2130771969;
-
- static String()
- {
- global::Android.Runtime.ResourceIdManager.UpdateIdValues();
- }
-
- private String()
- {
- }
- }
- }
-}
-#pragma warning restore 1591
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Values/Strings.xml b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Values/Strings.xml
deleted file mode 100644
index 8fd1763..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Resources/Values/Strings.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- Hello World, Click Me!
- $projectname$
-
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/UsbSerialForAndroid.csproj b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/UsbSerialForAndroid.csproj
deleted file mode 100644
index 246504a..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/UsbSerialForAndroid.csproj
+++ /dev/null
@@ -1,87 +0,0 @@
-
-
-
- Debug
- AnyCPU
- 8.0.30703
- 2.0
- {A64567BC-548A-4CB7-9F2C-ECE75EE1A868}
- {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
- Library
- Properties
- Hoho.Android.UsbSerial
- Android.UsbSerial
- 512
- Resources\Resource.Designer.cs
- Off
- False
- v12.0
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Util/HexDump.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Util/HexDump.cs
deleted file mode 100644
index 32dc2a5..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/Util/HexDump.cs
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Text;
-
-namespace Hoho.Android.UsbSerial.Util
-{
- public class HexDump
- {
- private static char[] HEX_DIGITS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
- };
-
- public static string DumpHexString(byte[] array)
- {
- return DumpHexString(array, 0, array.Length);
- }
- public static string DumpHexString(byte[] array, int offset, int length)
- {
- StringBuilder result = new StringBuilder();
-
- byte[] line = new byte[16];
- int lineIndex = 0;
-
- result.Append("\n0x");
- result.Append(ToHexString(offset));
-
- for (int i = offset; i < offset + length; i++)
- {
- if (lineIndex == 16)
- {
- result.Append(" ");
-
- for (int j = 0; j < 16; j++)
- {
- if (line[j] > ' ' && line[j] < '~')
- {
- result.Append(System.Text.Encoding.Default.GetString(line).Substring(j, 1));
- }
- else
- {
- result.Append(".");
- }
- }
-
- result.Append("\n0x");
- result.Append(ToHexString(i));
- lineIndex = 0;
- }
-
- byte b = array[i];
- result.Append(" ");
- result.Append(HEX_DIGITS[(b >> 4) & 0x0F]);
- result.Append(HEX_DIGITS[b & 0x0F]);
-
- line[lineIndex++] = b;
- }
-
- if (lineIndex != 16)
- {
- int count = (16 - lineIndex) * 3;
- count++;
- for (int i = 0; i < count; i++)
- {
- result.Append(" ");
- }
-
- for (int i = 0; i < lineIndex; i++)
- {
- if (line[i] > ' ' && line[i] < '~')
- {
- result.Append(System.Text.Encoding.Default.GetString(line).Substring(i, 1));
- }
- else
- {
- result.Append(".");
- }
- }
- }
-
- return result.ToString();
- }
-
- public static string ToHexString(byte[] byteArray)
- {
- return BitConverter.ToString(byteArray).Replace("-", "");
- }
-
- public static string ToHexString(byte[] byteArray, int offset, int length)
- {
- StringBuilder hex = new StringBuilder(length*2);
-
- while ((offset < byteArray.Length) && (length > 0))
- {
- hex.AppendFormat("{0:x2}", byteArray[offset]);
-
- offset++;
- length--;
- }
- return hex.ToString();
- }
-
- public static string ToHexString(int i)
- {
- return ToHexString(ToByteArray(i));
- }
-
- public static string ToHexString(short i)
- {
- return ToHexString(ToByteArray(i));
- }
-
- public static byte[] ToByteArray(byte b)
- {
- return new byte[] {b};
- }
-
- public static byte[] ToByteArray(int i)
- {
- byte[] array = new byte[4];
-
- array[3] = (byte) (i & 0xFF);
- array[2] = (byte) ((i >> 8) & 0xFF);
- array[1] = (byte) ((i >> 16) & 0xFF);
- array[0] = (byte) ((i >> 24) & 0xFF);
-
- return array;
- }
-
- public static byte[] ToByteArray(short i)
- {
- byte[] array = new byte[2];
-
- array[1] = (byte) (i & 0xFF);
- array[0] = (byte) ((i >> 8) & 0xFF);
-
- return array;
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CdcAcmSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CdcAcmSerialDriver.cs
deleted file mode 100644
index 30f2300..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CdcAcmSerialDriver.cs
+++ /dev/null
@@ -1,509 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System.Collections.Generic;
-using Android.Hardware.Usb;
-using Android.OS;
-using Android.Util;
-using Hoho.Android.UsbSerial.Extensions;
-using Hoho.Android.UsbSerial.Util;
-using Java.IO;
-using Java.Lang;
-using Java.Nio;
-using Math = System.Math;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class CdcAcmSerialDriver : UsbSerialDriver
- {
- private static string TAG = typeof(CdcAcmSerialDriver).Name;
-
- public CdcAcmSerialDriver(UsbDevice device, bool? enableAsyncReads = null)
- {
- mDevice = device;
- mPort = new CdcAcmSerialPort(device, 0, this, enableAsyncReads);
- }
-
- // Additional constructor for ProbeDevice called by Reflection
- // Note that this defaults to enableAsyncReads = false as
- // there is no support for passing additional arguments from ProbeDevice
- public CdcAcmSerialDriver(UsbDevice device)
- {
- mDevice = device;
- bool enableAsyncReads = false; // For clarity of understanding
- mPort = new CdcAcmSerialPort(device, 0, this, enableAsyncReads);
- }
-
- class CdcAcmSerialPort : CommonUsbSerialPort
- {
- private bool mEnableAsyncReads;
- private UsbInterface mControlInterface;
- private UsbInterface mDataInterface;
-
- private UsbEndpoint mControlEndpoint;
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
-
- private bool mRts = false;
- private bool mDtr = false;
-
- private static int USB_RECIP_INTERFACE = 0x01;
- private static int USB_RT_ACM = UsbConstants.UsbTypeClass | USB_RECIP_INTERFACE;
-
- private static int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2
- private static int GET_LINE_CODING = 0x21;
- private static int SET_CONTROL_LINE_STATE = 0x22;
- private static int SEND_BREAK = 0x23;
-
- private IUsbSerialDriver Driver;
-
- //public CdcAcmSerialPort(UsbDevice device, int portNumber) : base(device, portNumber)
- //{
- // mEnableAsyncReads = (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1);
- //}
-
- public CdcAcmSerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver, bool? enableAsyncReads = null) : base(device, portNumber)
- {
- if (enableAsyncReads != null)
- {
- mEnableAsyncReads = enableAsyncReads.Value;
- }
- else
- {
- mEnableAsyncReads = (Build.VERSION.SdkInt >= BuildVersionCodes.JellyBeanMr1);
-
- }
- this.Driver = driver;
- }
-
-
- public override IUsbSerialDriver GetDriver()
- {
- return Driver;
- }
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null)
- {
- throw new IOException("Already open");
- }
-
- mConnection = connection;
- bool opened = false;
-
- try
- {
- if (1 == mDevice.InterfaceCount)
- {
- Log.Debug(TAG, "device might be castrated ACM device, trying single interface logic");
- OpenSingleInterface();
- }
- else
- {
- Log.Debug(TAG, "trying default interface logic");
- openInterface();
- }
-
- if (mEnableAsyncReads)
- {
- Log.Debug(TAG, "Async reads enabled");
- }
- else
- {
- Log.Debug(TAG, "Async reads disabled.");
- }
-
-
- opened = true;
- }
- finally
- {
- if (!opened)
- {
- mConnection = null;
- // just to be on the save side
- mControlEndpoint = null;
- mReadEndpoint = null;
- mWriteEndpoint = null;
- }
- }
- }
-
- private void OpenSingleInterface()
- {
- // the following code is inspired by the cdc-acm driver
- // in the linux kernel
-
- mControlInterface = mDevice.GetInterface(0);
- Log.Debug(TAG, "Control iface=" + mControlInterface);
-
- mDataInterface = mDevice.GetInterface(0);
- Log.Debug(TAG, "data iface=" + mDataInterface);
-
- if (!mConnection.ClaimInterface(mControlInterface, true))
- {
- throw new IOException("Could not claim shared control/data interface.");
- }
-
- int endCount = mControlInterface.EndpointCount;
-
- if (endCount < 3)
- {
- Log.Debug(TAG, "not enough endpoints - need 3. count=" + endCount);
- throw new IOException("Insufficient number of endpoints(" + endCount + ")");
- }
-
- // Analyse endpoints for their properties
- mControlEndpoint = null;
- mReadEndpoint = null;
- mWriteEndpoint = null;
- for (int i = 0; i < endCount; ++i)
- {
- UsbEndpoint ep = mControlInterface.GetEndpoint(i);
- if ((ep.Direction == UsbAddressing.In) &&
- (ep.Type == UsbAddressing.XferInterrupt))
- {
- Log.Debug(TAG, "Found controlling endpoint");
- mControlEndpoint = ep;
- }
- else if ((ep.Direction == UsbAddressing.In) &&
- (ep.Type == UsbAddressing.XferBulk))
- {
- Log.Debug(TAG, "Found reading endpoint");
- mReadEndpoint = ep;
- }
- else if ((ep.Direction == UsbAddressing.Out) &&
- (ep.Type == UsbAddressing.XferBulk))
- {
- Log.Debug(TAG, "Found writing endpoint");
- mWriteEndpoint = ep;
- }
-
-
- if ((mControlEndpoint != null) &&
- (mReadEndpoint != null) &&
- (mWriteEndpoint != null))
- {
- Log.Debug(TAG, "Found all required endpoints");
- break;
- }
- }
-
- if ((mControlEndpoint == null) ||
- (mReadEndpoint == null) ||
- (mWriteEndpoint == null))
- {
- Log.Debug(TAG, "Could not establish all endpoints");
- throw new IOException("Could not establish all endpoints");
- }
- }
-
- private void openInterface()
- {
- Log.Debug(TAG, "claiming interfaces, count=" + mDevice.InterfaceCount);
-
- mControlInterface = mDevice.GetInterface(0);
- Log.Debug(TAG, "Control iface=" + mControlInterface);
- // class should be USB_CLASS_COMM
-
- if (!mConnection.ClaimInterface(mControlInterface, true))
- {
- throw new IOException("Could not claim control interface.");
- }
-
- mControlEndpoint = mControlInterface.GetEndpoint(0);
- Log.Debug(TAG, "Control endpoint direction: " + mControlEndpoint.Direction);
-
- Log.Debug(TAG, "Claiming data interface.");
- mDataInterface = mDevice.GetInterface(1);
- Log.Debug(TAG, "data iface=" + mDataInterface);
- // class should be USB_CLASS_CDC_DATA
-
- if (!mConnection.ClaimInterface(mDataInterface, true))
- {
- throw new IOException("Could not claim data interface.");
- }
- mReadEndpoint = mDataInterface.GetEndpoint(1);
- Log.Debug(TAG, "Read endpoint direction: " + mReadEndpoint.Direction);
- mWriteEndpoint = mDataInterface.GetEndpoint(0);
- Log.Debug(TAG, "Write endpoint direction: " + mWriteEndpoint.Direction);
- }
-
- private int SendAcmControlMessage(int request, int value, byte[] buf)
- {
- return mConnection.ControlTransfer((UsbAddressing)0x21,
- request, value, 0, buf, buf != null ? buf.Length : 0, 5000);
- }
-
- public override void Close()
- {
- if (mConnection == null)
- {
- throw new IOException("Already closed");
- }
- mConnection.Close();
- mConnection = null;
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- if (mEnableAsyncReads)
- {
- UsbRequest request = new UsbRequest();
- try
- {
- request.Initialize(mConnection, mReadEndpoint);
-
- // CJM: Xamarin bug: ByteBuffer.Wrap is supposed to be a two way update
- // Changes made to one buffer should reflect in the other. It's not working
- // As a work around, I added a new method as an extension that uses JNI to turn
- // a new byte[] array. I then used BlockCopy to copy the bytes back the original array
- // see https://forums.xamarin.com/discussion/comment/238396/#Comment_238396
- //
- // Old work around:
- // as a work around, we populate dest with a call to buf.Get()
- // see https://bugzilla.xamarin.com/show_bug.cgi?id=20772
- // and https://bugzilla.xamarin.com/show_bug.cgi?id=31260
-
- ByteBuffer buf = ByteBuffer.Wrap(dest);
- if (!request.Queue(buf, dest.Length))
- {
- throw new IOException("Error queueing request.");
- }
-
- UsbRequest response = mConnection.RequestWait();
- if (response == null)
- {
- throw new IOException("Null response");
- }
-
- int nread = buf.Position();
- if (nread > 0)
- {
- // CJM: This differs from the Java implementation. The dest buffer was
- // not getting the data back.
-
- // 1st work around, no longer used
- //buf.Rewind();
- //buf.Get(dest, 0, dest.Length);
-
- System.Buffer.BlockCopy(buf.ToByteArray(), 0, dest, 0, dest.Length);
-
- Log.Debug(TAG, HexDump.DumpHexString(dest, 0, Math.Min(32, dest.Length)));
- return nread;
- }
- else
- {
- return 0;
- }
- }
- finally
- {
- request.Close();
- }
- }
-
- int numBytesRead;
- lock (mReadBufferLock)
- {
- int readAmt = Math.Min(dest.Length, mReadBuffer.Length);
- numBytesRead = mConnection.BulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0)
- {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- if (timeoutMillis == Integer.MaxValue)
- {
- // Hack: Special case "~infinite timeout" as an error.
- return -1;
- }
- return 0;
- }
- System.Buffer.BlockCopy(mReadBuffer, 0, dest, 0, numBytesRead);
- }
- return numBytesRead;
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- // TODO(mikey): Nearly identical to FtdiSerial write. Refactor.
- int offset = 0;
-
- while (offset < src.Length)
- {
- int writeLength;
- int amtWritten;
-
- lock (mWriteBufferLock)
- {
- byte[] writeBuffer;
-
- writeLength = Math.Min(src.Length - offset, mWriteBuffer.Length);
- if (offset == 0)
- {
- writeBuffer = src;
- }
- else
- {
- // bulkTransfer does not support offsets, make a copy.
- System.Buffer.BlockCopy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
- }
-
- amtWritten = mConnection.BulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
- timeoutMillis);
- }
- if (amtWritten <= 0)
- {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length=" + src.Length);
- }
-
- Log.Debug(TAG, "Wrote amt=" + amtWritten + " attempted=" + writeLength);
- offset += amtWritten;
- }
- return offset;
- }
-
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- byte stopBitsByte;
- switch (stopBits)
- {
- case StopBits.One: stopBitsByte = 0; break;
- case StopBits.OnePointFive: stopBitsByte = 1; break;
- case StopBits.Two: stopBitsByte = 2; break;
- default: throw new IllegalArgumentException("Bad value for stopBits: " + stopBits);
- }
-
- byte parityBitesByte;
- switch (parity)
- {
- case Parity.None: parityBitesByte = 0; break;
- case Parity.Odd: parityBitesByte = 1; break;
- case Parity.Even: parityBitesByte = 2; break;
- case Parity.Mark: parityBitesByte = 3; break;
- case Parity.Space: parityBitesByte = 4; break;
- default: throw new IllegalArgumentException("Bad value for parity: " + parity);
- }
-
- byte[] msg = {
- (byte) ( baudRate & 0xff),
- (byte) ((baudRate >> 8 ) & 0xff),
- (byte) ((baudRate >> 16) & 0xff),
- (byte) ((baudRate >> 24) & 0xff),
- stopBitsByte,
- parityBitesByte,
- (byte) dataBits};
- SendAcmControlMessage(SET_LINE_CODING, 0, msg);
- }
-
- public override bool GetCD()
- {
- return false; // TODO
- }
-
- public override bool GetCTS()
- {
- return false; // TODO
- }
-
- public override bool GetDSR()
- {
- return false; // TODO
- }
-
- public override bool GetDTR()
- {
- return mDtr;
- }
-
- public override void SetDTR(bool value)
- {
- mDtr = value;
- SetDtrRts();
- }
-
- public override bool GetRI()
- {
- return false; // TODO
- }
-
- public override bool GetRTS()
- {
- return mRts;
- }
-
- public override void SetRTS(bool value)
- {
- mRts = value;
- SetDtrRts();
- }
-
- private void SetDtrRts()
- {
- int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
- SendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
- }
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_ARDUINO, new[]
- {
- UsbId.ARDUINO_UNO,
- UsbId.ARDUINO_UNO_R3,
- UsbId.ARDUINO_MEGA_2560,
- UsbId.ARDUINO_MEGA_2560_R3,
- UsbId.ARDUINO_SERIAL_ADAPTER,
- UsbId.ARDUINO_SERIAL_ADAPTER_R3,
- UsbId.ARDUINO_MEGA_ADK,
- UsbId.ARDUINO_MEGA_ADK_R3,
- UsbId.ARDUINO_LEONARDO,
- UsbId.ARDUINO_MICRO,
- }
- },
- {
- UsbId.VENDOR_VAN_OOIJEN_TECH, new[]
- {
- UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL
- }
- },
- {
- UsbId.VENDOR_ATMEL, new[]
- {
- UsbId.ATMEL_LUFA_CDC_DEMO_APP
- }
- },
- {
- UsbId.VENDOR_ELATEC, new[]
- {
- UsbId.ELATEC_TWN3_CDC,
- UsbId.ELATEC_TWN4_MIFARE_NFC,
- UsbId.ELATEC_TWN4_CDC,
- }
- },
- {
- UsbId.VENDOR_LEAFLABS, new[]
- {
- UsbId.LEAFLABS_MAPLE
- }
- }
- };
- }
- }
-
-
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Ch34xSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Ch34xSerialDriver.cs
deleted file mode 100644
index f910d76..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Ch34xSerialDriver.cs
+++ /dev/null
@@ -1,379 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Android.Hardware.Usb;
-using Android.Util;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class Ch34xSerialDriver : UsbSerialDriver
- {
- private readonly string TAG = typeof (ProlificSerialDriver).Name;
-
- public Ch34xSerialDriver(UsbDevice device)
- {
- mDevice = device;
- mPort = new Ch340SerialPort(mDevice, 0, this);
- }
-
- public class Ch340SerialPort : CommonUsbSerialPort
- {
- private static int USB_TIMEOUT_MILLIS = 5000;
-
- private int DEFAULT_BAUD_RATE = 9600;
-
- private Boolean dtr = false;
- private Boolean rts = false;
-
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
-
- private IUsbSerialDriver Driver;
- private string TAG => (Driver as Ch34xSerialDriver)?.TAG;
-
- public Ch340SerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver) : base(device, portNumber)
- {
- Driver = driver;
- }
-
- public override IUsbSerialDriver GetDriver()
- {
- return Driver;
- }
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null)
- {
- throw new IOException("Already opened.");
- }
-
- mConnection = connection;
- Boolean opened = false;
- try
- {
- for (int i = 0; i < mDevice.InterfaceCount; i++)
- {
- UsbInterface usbIface = mDevice.GetInterface(i);
- if (mConnection.ClaimInterface(usbIface, true))
- {
- Log.Debug(TAG, "claimInterface " + i + " SUCCESS");
- }
- else
- {
- Log.Debug(TAG, "claimInterface " + i + " FAIL");
- }
- }
-
- UsbInterface dataIface = mDevice.GetInterface(mDevice.InterfaceCount - 1);
- for (int i = 0; i < dataIface.EndpointCount; i++)
- {
- UsbEndpoint ep = dataIface.GetEndpoint(i);
- if (ep.Type == (UsbAddressing) UsbSupport.UsbEndpointXferBulk)
- {
- if (ep.Direction == (UsbAddressing) UsbSupport.UsbDirIn)
- {
- mReadEndpoint = ep;
- }
- else
- {
- mWriteEndpoint = ep;
- }
- }
- }
-
-
- Initialize();
- SetBaudRate(DEFAULT_BAUD_RATE);
-
- opened = true;
- }
- finally
- {
- if (!opened)
- {
- try
- {
- Close();
- }
- catch (IOException e)
- {
- // Ignore IOExceptions during close()
- }
- }
- }
- }
-
- public override void Close()
- {
- if (mConnection == null)
- {
- throw new IOException("Already closed");
- }
-
- // TODO: nothing sended on close, maybe needed?
-
- try
- {
- mConnection.Close();
- }
- finally
- {
- mConnection = null;
- }
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- int numBytesRead;
- lock (mReadBufferLock)
- {
- int readAmt = Math.Min(dest.Length, mReadBuffer.Length);
- numBytesRead = mConnection.BulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0)
- {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- return 0;
- }
- Buffer.BlockCopy(mReadBuffer, 0, dest, 0, numBytesRead);
- }
- return numBytesRead;
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- int offset = 0;
-
- while (offset < src.Length)
- {
- int writeLength;
- int amtWritten;
-
- lock (mWriteBufferLock)
- {
- byte[] writeBuffer;
-
- writeLength = Math.Min(src.Length - offset, mWriteBuffer.Length);
- if (offset == 0)
- {
- writeBuffer = src;
- }
- else
- {
- // bulkTransfer does not support offsets, make a copy.
- Buffer.BlockCopy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
- }
-
- amtWritten = mConnection.BulkTransfer(mWriteEndpoint, writeBuffer, writeLength,
- timeoutMillis);
- }
- if (amtWritten <= 0)
- {
- throw new IOException(
- $"Error writing {writeLength} bytes at offset {offset} length={src.Length}");
- }
-
- Log.Debug(TAG, $"Wrote amt={amtWritten} attempted={writeLength}");
- offset += amtWritten;
- }
- return offset;
- }
-
- private int ControlOut(int request, int value, int index)
- {
- int REQTYPE_HOST_TO_DEVICE = 0x41;
- return mConnection.ControlTransfer((UsbAddressing) REQTYPE_HOST_TO_DEVICE, request,
- value, index, null, 0, USB_TIMEOUT_MILLIS);
- }
-
-
- private int ControlIn(int request, int value, int index, byte[] buffer)
- {
- int REQTYPE_HOST_TO_DEVICE = UsbConstants.UsbTypeVendor | UsbSupport.UsbDirIn;
- return mConnection.ControlTransfer((UsbAddressing) REQTYPE_HOST_TO_DEVICE, request,
- value, index, buffer, buffer.Length, USB_TIMEOUT_MILLIS);
- }
-
- private void CheckState(String msg, int request, int value, int[] expected)
- {
- byte[] buffer = new byte[expected.Length];
- int ret = ControlIn(request, value, 0, buffer);
-
- if (ret < 0)
- {
- throw new IOException($"Failed send cmd [{msg}]");
- }
-
- if (ret != expected.Length)
- {
- throw new IOException($"Expected {expected.Length} bytes, but get {ret} [{msg}]");
- }
-
- for (int i = 0; i < expected.Length; i++)
- {
- if (expected[i] == -1)
- {
- continue;
- }
-
- int current = buffer[i] & 0xff;
- if (expected[i] != current)
- {
- throw new IOException($"Expected 0x{expected[i]:X} bytes, but get 0x{current:X} [ {msg} ]");
- }
- }
- }
-
- private void WriteHandshakeByte()
- {
- if (ControlOut(0xa4, ~((dtr ? 1 << 5 : 0) | (rts ? 1 << 6 : 0)), 0) < 0)
- {
- throw new IOException("Failed to set handshake byte");
- }
- }
-
- private void Initialize()
- {
- CheckState("init #1", 0x5f, 0, new int[] {-1 /* 0x27, 0x30 */, 0x00});
-
- if (ControlOut(0xa1, 0, 0) < 0)
- {
- throw new IOException("init failed! #2");
- }
-
- SetBaudRate(DEFAULT_BAUD_RATE);
-
- CheckState("init #4", 0x95, 0x2518, new int[] {-1 /* 0x56, c3*/, 0x00});
-
- if (ControlOut(0x9a, 0x2518, 0x0050) < 0)
- {
- throw new IOException("init failed! #5");
- }
-
- CheckState("init #6", 0x95, 0x0706, new int[] {0xff, 0xee});
-
- if (ControlOut(0xa1, 0x501f, 0xd90a) < 0)
- {
- throw new IOException("init failed! #7");
- }
-
- SetBaudRate(DEFAULT_BAUD_RATE);
-
- WriteHandshakeByte();
-
- CheckState("init #10", 0x95, 0x0706, new int[] {-1 /* 0x9f, 0xff*/, 0xee});
- }
-
- private void SetBaudRate(int baudRate)
- {
- int[] baud = new int[]
- {
- 2400, 0xd901, 0x0038, 4800, 0x6402,
- 0x001f, 9600, 0xb202, 0x0013, 19200, 0xd902, 0x000d, 38400,
- 0x6403, 0x000a, 115200, 0xcc03, 0x0008
- };
-
- for (int i = 0; i < baud.Length/3; i++)
- {
- if (baud[i*3] == baudRate)
- {
- int ret = ControlOut(0x9a, 0x1312, baud[i*3 + 1]);
- if (ret < 0)
- {
- throw new IOException("Error setting baud rate. #1");
- }
- ret = ControlOut(0x9a, 0x0f2c, baud[i*3 + 2]);
- if (ret < 0)
- {
- throw new IOException("Error setting baud rate. #1");
- }
-
- return;
- }
- }
-
-
- throw new IOException("Baud rate " + baudRate + " currently not supported");
- }
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- SetBaudRate(baudRate);
-
- // TODO databit, stopbit and paraty set not implemented
- }
-
- public override bool GetCD()
- {
- return false;
- }
-
- public override bool GetCTS()
- {
- return false;
- }
-
- public override bool GetDSR()
- {
- return false;
- }
-
- public override bool GetDTR()
- {
- return dtr;
- }
-
- public override void SetDTR(bool value)
- {
- dtr = value;
- WriteHandshakeByte();
- }
-
- public override bool GetRI()
- {
- return false;
- }
-
- public override bool GetRTS()
- {
- return rts;
- }
-
- public override void SetRTS(bool value)
- {
- rts = value;
- WriteHandshakeByte();
- }
-
- public override bool PurgeHwBuffers(bool flushReadBuffers, bool flushWriteBuffers)
- {
- return true;
- }
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_QINHENG, new int[]
- {
- UsbId.QINHENG_HL340
- }
- }
- };
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CommonUsbSerialPort.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CommonUsbSerialPort.cs
deleted file mode 100644
index 90cf4be..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/CommonUsbSerialPort.cs
+++ /dev/null
@@ -1,139 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using Android.Hardware.Usb;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public abstract class CommonUsbSerialPort : UsbSerialPort
- {
- public static int DEFAULT_READ_BUFFER_SIZE = 16 * 1024;
- public static int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024;
-
- protected UsbDevice mDevice;
- protected int mPortNumber;
-
- // non-null when open()
- protected UsbDeviceConnection mConnection = null;
-
- // check if connection is still available
- public bool HasConnection => mConnection != null;
-
- protected object mReadBufferLock = new object();
- protected object mWriteBufferLock = new object();
-
- /** Internal read buffer. Guarded by {@link #mReadBufferLock}. */
- protected byte[] mReadBuffer;
-
- /** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */
- protected byte[] mWriteBuffer;
-
- public CommonUsbSerialPort(UsbDevice device, int portNumber)
- {
- mDevice = device;
- mPortNumber = portNumber;
-
- mReadBuffer = new byte[DEFAULT_READ_BUFFER_SIZE];
- mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE];
- }
- public override string ToString()
- {
- return
- $"<{this.GetType().Name} device_name={mDevice.DeviceName} device_id={mDevice.DeviceId} port_number={mPortNumber}>";
- }
-
- /**
- * Returns the currently-bound USB device.
- *
- * @return the device
- */
- public UsbDevice GetDevice()
- {
- return mDevice;
- }
-
- public override int GetPortNumber()
- {
- return mPortNumber;
- }
-
- /**
- * Returns the device serial number
- * @return serial number
- */
- public override string GetSerial()
- {
- return mConnection.Serial;
- }
-
- /**
- * Sets the size of the internal buffer used to exchange data with the USB
- * stack for read operations. Most users should not need to change this.
- *
- * @param bufferSize the size in bytes
- */
- public void SetReadBufferSize(int bufferSize)
- {
- lock(mReadBufferLock) {
- if (bufferSize == mReadBuffer.Length)
- {
- return;
- }
- mReadBuffer = new byte[bufferSize];
- }
- }
-
- /**
- * Sets the size of the internal buffer used to exchange data with the USB
- * stack for write operations. Most users should not need to change this.
- *
- * @param bufferSize the size in bytes
- */
- public void SetWriteBufferSize(int bufferSize)
- {
- lock(mWriteBufferLock) {
- if (bufferSize == mWriteBuffer.Length)
- {
- return;
- }
- mWriteBuffer = new byte[bufferSize];
- }
- }
-
- public abstract override void Open(UsbDeviceConnection connection);
-
- public abstract override void Close();
-
- public abstract override int Read(byte[] dest, int timeoutMillis);
-
- public abstract override int Write(byte[] src, int timeoutMillis);
-
- public abstract override void SetParameters(
- int baudRate, int dataBits, StopBits stopBits, Parity parity);
-
- public abstract override bool GetCD();
-
- public abstract override bool GetCTS();
-
- public abstract override bool GetDSR();
-
- public abstract override bool GetDTR();
-
- public abstract override void SetDTR(bool value);
-
- public abstract override bool GetRI();
-
- public abstract override bool GetRTS();
-
- public abstract override void SetRTS(bool value);
-
- public override bool PurgeHwBuffers(bool flushReadBuffers, bool flushWriteBuffers)
- {
- return !flushReadBuffers && !flushWriteBuffers;
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Cp21xxSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Cp21xxSerialDriver.cs
deleted file mode 100644
index bb4eed2..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Cp21xxSerialDriver.cs
+++ /dev/null
@@ -1,373 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Android.Hardware.Usb;
-using Android.Util;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class Cp21xxSerialDriver : UsbSerialDriver
- {
- private readonly string TAG = typeof(Cp21xxSerialDriver).Name;
-
- public Cp21xxSerialDriver(UsbDevice device)
- {
- mDevice = device;
- mPort = new Cp21xxSerialPort(mDevice, 0, this);
- }
-
- public class Cp21xxSerialPort : CommonUsbSerialPort
- {
- private const int DEFAULT_BAUD_RATE = 9600;
-
- private const int USB_WRITE_TIMEOUT_MILLIS = 5000;
-
- /*
- * Configuration Request Types
- */
- private const int REQTYPE_HOST_TO_DEVICE = 0x41;
- private const int REQTYPE_DEVICE_TO_HOST = 0xc1;
-
- /*
- * Configuration Request Codes
- */
- private const int SILABSER_IFC_ENABLE_REQUEST_CODE = 0x00;
- private const int SILABSER_SET_BAUDDIV_REQUEST_CODE = 0x01;
- private const int SILABSER_SET_LINE_CTL_REQUEST_CODE = 0x03;
- private const int SILABSER_SET_MHS_REQUEST_CODE = 0x07;
- private const int SILABSER_SET_BAUDRATE = 0x1E;
- private const int SILABSER_FLUSH_REQUEST_CODE = 0x12;
-
- private const int FLUSH_READ_CODE = 0x0a;
- private const int FLUSH_WRITE_CODE = 0x05;
-
- private const int GET_MODEM_STATUS_REQUEST = 0x08; // 0x08 Get modem status.
- private const int MODEM_STATUS_CTS = 0x10;
- private const int MODEM_STATUS_DSR = 0x20;
- private const int MODEM_STATUS_RI = 0x40;
- private const int MODEM_STATUS_CD = 0x80;
- /*
- * SILABSER_IFC_ENABLE_REQUEST_CODE
- */
- private const int UART_ENABLE = 0x0001;
- private const int UART_DISABLE = 0x0000;
-
- /*
- * SILABSER_SET_BAUDDIV_REQUEST_CODE
- */
- private const int BAUD_RATE_GEN_FREQ = 0x384000;
-
- /*
- * SILABSER_SET_MHS_REQUEST_CODE
- */
- private const int MCR_DTR = 0x0001;
- private const int MCR_RTS = 0x0002;
- private const int MCR_ALL = 0x0003;
-
- private const int CONTROL_WRITE_DTR = 0x0100;
- private const int CONTROL_WRITE_RTS = 0x0200;
-
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
-
- private new IUsbSerialDriver Driver;
- private string TAG => (Driver as Cp21xxSerialDriver)?.TAG;
-
-
-
- public Cp21xxSerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver) : base(device, portNumber)
- {
- Driver = driver;
- }
-
- public override IUsbSerialDriver GetDriver()
- {
- return Driver;
- }
-
- private int SetConfigSingle(int request, int value)
- {
- return mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, request, value,
- 0, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- }
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null)
- {
- throw new IOException("Already opened.");
- }
-
- mConnection = connection;
- Boolean opened = false;
- try
- {
- for (int i = 0; i < mDevice.InterfaceCount; i++)
- {
- UsbInterface usbIface = mDevice.GetInterface(i);
- if (mConnection.ClaimInterface(usbIface, true))
- {
- Log.Debug(TAG, $"claimInterface {i} SUCCESS");
- }
- else
- {
- Log.Debug(TAG, $"claimInterface {i} FAIL");
- }
- }
-
- UsbInterface dataIface = mDevice.GetInterface(mDevice.InterfaceCount - 1);
- for (int i = 0; i < dataIface.EndpointCount; i++)
- {
- UsbEndpoint ep = dataIface.GetEndpoint(i);
- if (ep.Type == (UsbAddressing)UsbSupport.UsbEndpointXferBulk)
- {
- if (ep.Direction == (UsbAddressing)UsbSupport.UsbDirIn)
- {
- mReadEndpoint = ep;
- }
- else
- {
- mWriteEndpoint = ep;
- }
- }
- }
-
- SetConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_ENABLE);
- SetConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, MCR_ALL | CONTROL_WRITE_DTR | CONTROL_WRITE_RTS);
- SetConfigSingle(SILABSER_SET_BAUDDIV_REQUEST_CODE, BAUD_RATE_GEN_FREQ / DEFAULT_BAUD_RATE);
- // setParameters(DEFAULT_BAUD_RATE, DEFAULT_DATA_BITS, DEFAULT_STOP_BITS, DEFAULT_PARITY);
- opened = true;
- }
- finally
- {
- if (!opened)
- {
- try
- {
- Close();
- }
- catch (IOException e)
- {
- // Ignore IOExceptions during close()
- }
- }
- }
- }
-
- public override void Close()
- {
- if (mConnection == null)
- {
- throw new IOException("Already closed");
- }
- try
- {
- SetConfigSingle(SILABSER_IFC_ENABLE_REQUEST_CODE, UART_DISABLE);
- mConnection.Close();
- }
- finally
- {
- mConnection = null;
- }
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- int numBytesRead;
- lock(mReadBufferLock) {
- int readAmt = Math.Min(dest.Length, mReadBuffer.Length);
- numBytesRead = mConnection.BulkTransfer(mReadEndpoint, mReadBuffer, readAmt,
- timeoutMillis);
- if (numBytesRead < 0)
- {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- return 0;
- }
- Buffer.BlockCopy(mReadBuffer, 0, dest, 0, numBytesRead);
- }
- return numBytesRead;
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- int offset = 0;
- int writeLength;
- int amtWritten;
-
- while (offset < src.Length)
- {
- lock(mWriteBufferLock) {
-
- writeLength = src.Length - offset;
-
- amtWritten = mConnection.BulkTransfer(mWriteEndpoint, src, offset, writeLength,
- timeoutMillis);
- }
- if (amtWritten <= 0)
- {
- throw new IOException(
- $"Error writing {writeLength} bytes at offset {offset} length={src.Length}");
- }
-
- Log.Debug(TAG, $"Wrote amt={amtWritten} attempted={writeLength}");
- offset += amtWritten;
- }
- return offset;
- }
-
- private void SetBaudRate(int baudRate)
- {
- byte[] data = new byte[] {
- (byte) ( baudRate & 0xff),
- (byte) ((baudRate >> 8 ) & 0xff),
- (byte) ((baudRate >> 16) & 0xff),
- (byte) ((baudRate >> 24) & 0xff)
- };
- int ret = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, SILABSER_SET_BAUDRATE,
- 0, 0, data, 4, USB_WRITE_TIMEOUT_MILLIS);
- if (ret < 0)
- {
- throw new IOException("Error setting baud rate.");
- }
- }
-
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- SetBaudRate(baudRate);
-
- int configDataBits = 0;
- switch (dataBits)
- {
- case DATABITS_5:
- configDataBits |= 0x0500;
- break;
- case DATABITS_6:
- configDataBits |= 0x0600;
- break;
- case DATABITS_7:
- configDataBits |= 0x0700;
- break;
- case DATABITS_8:
- configDataBits |= 0x0800;
- break;
- default:
- configDataBits |= 0x0800;
- break;
- }
-
- switch (parity)
- {
- case Parity.Odd:
- configDataBits |= 0x0010;
- break;
- case Parity.Even:
- configDataBits |= 0x0020;
- break;
- }
-
- switch (stopBits)
- {
- case StopBits.One:
- configDataBits |= 0;
- break;
- case StopBits.Two:
- configDataBits |= 2;
- break;
- }
- SetConfigSingle(SILABSER_SET_LINE_CTL_REQUEST_CODE, configDataBits);
- }
-
- private int GetStatus()
- {
- byte[] data = new byte[1];
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_DEVICE_TO_HOST, GET_MODEM_STATUS_REQUEST,
- 0, 0, data, data.Length, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 1)
- {
- throw new IOException("Get modem status failed: result=" + result);
- }
- return data[0];
- }
-
- public override bool GetCD()
- {
- return (GetStatus() & MODEM_STATUS_CD) != 0;
- }
-
- public override bool GetCTS()
- {
- return (GetStatus() & MODEM_STATUS_CTS) != 0;
- }
-
- public override bool GetDSR()
- {
- return (GetStatus() & MODEM_STATUS_DSR) != 0;
- }
-
- public override bool GetDTR()
- {
- return (GetStatus() & MCR_DTR) != 0;
- }
-
- public override void SetDTR(bool value)
- {
- SetConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, (value ? MCR_DTR : 0) | CONTROL_WRITE_DTR);
- }
-
- public override bool GetRI()
- {
- return (GetStatus() & MODEM_STATUS_RI) != 0;
- }
-
- public override bool GetRTS()
- {
- return (GetStatus() & MCR_RTS) != 0;
- }
-
- public override void SetRTS(bool value)
- {
- SetConfigSingle(SILABSER_SET_MHS_REQUEST_CODE, (value ? MCR_RTS : 0) | CONTROL_WRITE_RTS);
- }
-
- public override Boolean PurgeHwBuffers(Boolean purgeReadBuffers, Boolean purgeWriteBuffers)
- {
- int value = (purgeReadBuffers ? FLUSH_READ_CODE : 0)
- | (purgeWriteBuffers ? FLUSH_WRITE_CODE : 0);
-
- if (value != 0)
- {
- SetConfigSingle(SILABSER_FLUSH_REQUEST_CODE, value);
- }
-
- return true;
- }
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_SILABS, new int[]
- {
- UsbId.SILABS_CP2102,
- UsbId.SILABS_CP2105,
- UsbId.SILABS_CP2108,
- UsbId.SILABS_CP2110
- }
- }
- };
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/FtdiSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/FtdiSerialDriver.cs
deleted file mode 100644
index dbb69db..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/FtdiSerialDriver.cs
+++ /dev/null
@@ -1,489 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Android.Hardware.Usb;
-using Android.Util;
-using Java.Lang;
-using Boolean = System.Boolean;
-using Math = System.Math;
-using String = System.String;
-
-/*
- * driver is implemented from various information scattered over FTDI documentation
- *
- * baud rate calculation https://www.ftdichip.com/Support/Documents/AppNotes/AN232B-05_BaudRates.pdf
- * control bits https://www.ftdichip.com/Firmware/Precompiled/UM_VinculumFirmware_V205.pdf
- * device type https://www.ftdichip.com/Support/Documents/AppNotes/AN_233_Java_D2XX_for_Android_API_User_Manual.pdf -> bvdDevice
- *
- */
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class FtdiSerialDriver : UsbSerialDriver
- {
- private List mPorts;
- private enum DeviceType
- {
- TYPE_BM,
- TYPE_AM,
- TYPE_2232C,
- TYPE_R,
- TYPE_2232H,
- TYPE_4232H
- }
-
- public FtdiSerialDriver(UsbDevice device)
- {
- mDevice = device;
- mPort = new FtdiSerialPort(mDevice, 0, this);
-
- mPorts = new List();
-
- for (int port = 0; port < device.InterfaceCount; port++)
- {
- mPorts.Add(new FtdiSerialPort(mDevice, port, this));
- }
- }
-
- // Needs to refactored
- public override List GetPorts()
- {
- return mPorts;
- }
-
- private class FtdiSerialPort : CommonUsbSerialPort
- {
- private static int USB_WRITE_TIMEOUT_MILLIS = 5000;
- private static int READ_HEADER_LENGTH = 2; // contains MODEM_STATUS
-
- // https://developer.android.com/reference/android/hardware/usb/UsbConstants#USB_DIR_IN
- private static int REQTYPE_HOST_TO_DEVICE = UsbConstants.UsbTypeVendor | 128; // UsbConstants.USB_DIR_OUT;
- private static int REQTYPE_DEVICE_TO_HOST = UsbConstants.UsbTypeVendor | 0; // UsbConstants.USB_DIR_IN;
-
- private static int RESET_REQUEST = 0;
- private static int MODEM_CONTROL_REQUEST = 1;
- private static int SET_BAUD_RATE_REQUEST = 3;
- private static int SET_DATA_REQUEST = 4;
- private static int GET_MODEM_STATUS_REQUEST = 5;
- private static int SET_LATENCY_TIMER_REQUEST = 9;
- private static int GET_LATENCY_TIMER_REQUEST = 10;
-
- private static int MODEM_CONTROL_DTR_ENABLE = 0x0101;
- private static int MODEM_CONTROL_DTR_DISABLE = 0x0100;
- private static int MODEM_CONTROL_RTS_ENABLE = 0x0202;
- private static int MODEM_CONTROL_RTS_DISABLE = 0x0200;
- private static int MODEM_STATUS_CTS = 0x10;
- private static int MODEM_STATUS_DSR = 0x20;
- private static int MODEM_STATUS_RI = 0x40;
- private static int MODEM_STATUS_CD = 0x80;
- private static int RESET_ALL = 0;
- private static int RESET_PURGE_RX = 1;
- private static int RESET_PURGE_TX = 2;
-
- private Boolean baudRateWithPort = false;
- private Boolean dtr = false;
- private Boolean rts = false;
- private int breakConfig = 0;
-
- private IUsbSerialDriver Driver;
-
-
- private String TAG = typeof (FtdiSerialDriver).Name;
-
-
- public FtdiSerialPort(UsbDevice device, int portNumber) : base(device, portNumber)
- {
- }
-
- public FtdiSerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver) : base(device, portNumber)
- {
- this.Driver = driver;
- }
-
- public override IUsbSerialDriver GetDriver()
- {
- return Driver;
- }
-
- public void Reset()
- {
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, RESET_REQUEST,
- RESET_ALL, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0)
- {
- throw new IOException("Reset failed: result=" + result);
- }
- }
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null) {
- throw new IOException("Already open");
- }
- mConnection = connection;
-
- Boolean opened = false;
- try {
- for (int i = 0; i < mDevice.InterfaceCount; i++)
- {
- if (connection.ClaimInterface(mDevice.GetInterface(i), true))
- {
- Log.Debug(TAG, "claimInterface " + i + " SUCCESS");
- }
- else
- {
- throw new IOException("Error claiming interface " + i);
- }
- }
- Reset();
- opened = true;
- } finally {
- if (!opened)
- {
- Close();
- mConnection = null;
- }
- }
- }
-
- public override void Close()
- {
- if (mConnection == null)
- {
- throw new IOException("Already closed");
- }
- try
- {
- mConnection.Close();
- }
- finally
- {
- mConnection = null;
- }
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- UsbEndpoint endpoint = mDevice.GetInterface(0).GetEndpoint(0);
-
- int totalBytesRead;
-
- lock(mReadBufferLock) {
- int readAmt = Math.Min(dest.Length, mReadBuffer.Length);
-
- // todo: replace with async call
- totalBytesRead = mConnection.BulkTransfer(endpoint, mReadBuffer,
- readAmt, timeoutMillis);
-
- if (totalBytesRead < READ_HEADER_LENGTH)
- {
- throw new IOException("Expected at least " + READ_HEADER_LENGTH + " bytes");
- }
-
- return ReadFilter(dest, totalBytesRead, endpoint.MaxPacketSize);
- }
- }
-
- protected int ReadFilter(byte[] buffer, int totalBytesRead, int maxPacketSize)
- {
- int destPos = 0;
-
- for (int srcPos = 0; srcPos < totalBytesRead; srcPos += maxPacketSize)
- {
- int length = Math.Min(srcPos + maxPacketSize, totalBytesRead) - (srcPos + READ_HEADER_LENGTH);
- if (length < 0)
- throw new IOException("Expected at least " + READ_HEADER_LENGTH + " bytes");
-
- Buffer.BlockCopy(mReadBuffer, srcPos + READ_HEADER_LENGTH, buffer, destPos, length);
- destPos += length;
- }
- return destPos;
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- UsbEndpoint endpoint = mDevice.GetInterface(0).GetEndpoint(1);
- int offset = 0;
-
- while (offset < src.Length)
- {
- int writeLength;
- int amtWritten;
-
- lock (mWriteBufferLock)
- {
- byte[] writeBuffer;
-
- writeLength = Math.Min(src.Length - offset, mWriteBuffer.Length);
- if (offset == 0)
- {
- writeBuffer = src;
- }
- else
- {
- // bulkTransfer does not support offsets, make a copy.
- Buffer.BlockCopy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
- }
-
- amtWritten = mConnection.BulkTransfer(endpoint, writeBuffer, writeLength,
- timeoutMillis);
- }
-
- if (amtWritten <= 0)
- {
- throw new IOException("Error writing " + writeLength
- + " bytes at offset " + offset + " length=" + src.Length);
- }
-
- Log.Debug(TAG, "Wrote amtWritten=" + amtWritten + " attempted=" + writeLength);
- offset += amtWritten;
- }
- return offset;
- }
-
-
- private int SetBaudRate(int baudRate)
- {
- int divisor, subdivisor, effectiveBaudRate;
-
- if (baudRate > 3500000)
- {
- throw new UnsupportedOperationException("Baud rate to high");
- }
- else if (baudRate >= 2500000)
- {
- divisor = 0;
- subdivisor = 0;
- effectiveBaudRate = 3000000;
- }
- else if (baudRate >= 1750000)
- {
- divisor = 1;
- subdivisor = 0;
- effectiveBaudRate = 2000000;
- }
- else
- {
- divisor = (24000000 << 1) / baudRate;
- divisor = (divisor + 1) >> 1; // round
- subdivisor = divisor & 0x07;
- divisor >>= 3;
- if (divisor > 0x3fff) // exceeds bit 13 at 183 baud
- throw new UnsupportedOperationException("Baud rate to low");
- effectiveBaudRate = (24000000 << 1) / ((divisor << 3) + subdivisor);
- effectiveBaudRate = (effectiveBaudRate + 1) >> 1;
- }
- double baudRateError = Math.Abs(1.0 - (effectiveBaudRate / (double)baudRate));
- if (baudRateError >= 0.031) // can happen only > 1.5Mbaud
- throw new UnsupportedOperationException(String.Format("Baud rate deviation %.1f%% is higher than allowed 3%%", baudRateError * 100));
- int value = divisor;
- int index = 0;
- switch (subdivisor)
- {
- case 0: break; // 16,15,14 = 000 - sub-integer divisor = 0
- case 4: value |= 0x4000; break; // 16,15,14 = 001 - sub-integer divisor = 0.5
- case 2: value |= 0x8000; break; // 16,15,14 = 010 - sub-integer divisor = 0.25
- case 1: value |= 0xc000; break; // 16,15,14 = 011 - sub-integer divisor = 0.125
- case 3: value |= 0x0000; index |= 1; break; // 16,15,14 = 100 - sub-integer divisor = 0.375
- case 5: value |= 0x4000; index |= 1; break; // 16,15,14 = 101 - sub-integer divisor = 0.625
- case 6: value |= 0x8000; index |= 1; break; // 16,15,14 = 110 - sub-integer divisor = 0.75
- case 7: value |= 0xc000; index |= 1; break; // 16,15,14 = 111 - sub-integer divisor = 0.875
- }
- if (baudRateWithPort)
- {
- index <<= 8;
- index |= mPortNumber + 1;
- }
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, SET_BAUD_RATE_REQUEST,
- value, index, null, 0, USB_WRITE_TIMEOUT_MILLIS);
-
- if (result != 0)
- {
- throw new IOException("Setting baudrate failed: result=" + result);
- }
-
- return effectiveBaudRate;
- }
-
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- if (baudRate <= 0)
- {
- throw new IllegalArgumentException("Invalid baud rate: " + baudRate);
- }
-
- SetBaudRate(baudRate);
-
- int config = dataBits;
-
- switch (dataBits)
- {
- case DATABITS_5:
- case DATABITS_6:
- throw new UnsupportedOperationException("Unsupported data bits: " + dataBits);
- case DATABITS_7:
- case DATABITS_8:
- config |= dataBits;
- break;
- default:
- throw new IllegalArgumentException("Invalid data bits: " + dataBits);
- }
-
- switch (parity)
- {
- case Parity.None:
- break;
- case Parity.Odd:
- config |= 0x100;
- break;
- case Parity.Even:
- config |= 0x200;
- break;
- case Parity.Mark:
- config |= 0x300;
- break;
- case Parity.Space:
- config |= 0x400;
- break;
- default:
- throw new IllegalArgumentException("Unknown parity value: " + parity);
- }
-
- switch (stopBits)
- {
- case StopBits.One:
- break;
- case StopBits.OnePointFive:
- throw new UnsupportedOperationException("Unsupported stop bits: 1.5");
- case StopBits.Two:
- config |= 0x1000;
- break;
- default:
- throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
- }
-
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, SET_DATA_REQUEST,
- config, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
-
- if (result != 0)
- {
- throw new IOException("Setting parameters failed: result=" + result);
- }
- breakConfig = config;
- }
-
- private int GetStatus()
- {
- byte[] data = new byte[2];
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_DEVICE_TO_HOST, GET_MODEM_STATUS_REQUEST,
- 0, mPortNumber + 1, data, data.Length, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 2) {
- throw new IOException("Get modem status failed: result=" + result);
- }
- return data[0];
- }
-
- public override Boolean GetCD()
- {
- return (GetStatus() & MODEM_STATUS_CD) != 0;
- }
-
- public override Boolean GetCTS()
- {
- return (GetStatus() & MODEM_STATUS_CTS) != 0;
- }
-
- public override Boolean GetDSR()
- {
- return (GetStatus() & MODEM_STATUS_DSR) != 0;
- }
-
- public override Boolean GetDTR()
- {
- return dtr;
- }
-
- public override void SetDTR(Boolean value)
- {
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, MODEM_CONTROL_REQUEST,
- value ? MODEM_CONTROL_DTR_ENABLE : MODEM_CONTROL_DTR_DISABLE, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0)
- {
- throw new IOException("Set DTR failed: result=" + result);
- }
- dtr = value;
- }
-
- public override Boolean GetRI()
- {
- return (GetStatus() & MODEM_STATUS_RI) != 0;
- }
-
- public override Boolean GetRTS()
- {
- return rts;
- }
-
- public override void SetRTS(Boolean value)
- {
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, MODEM_CONTROL_REQUEST,
- value ? MODEM_CONTROL_RTS_ENABLE : MODEM_CONTROL_RTS_DISABLE, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0)
- {
- throw new IOException("Set RTS failed: result=" + result);
- }
- rts = value;
- }
-
- public override Boolean PurgeHwBuffers(Boolean purgeReadBuffers, Boolean purgeWriteBuffers)
- {
- if (purgeWriteBuffers)
- {
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, RESET_REQUEST,
- RESET_PURGE_RX, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0)
- {
- throw new IOException("Flushing RX failed: result=" + result);
- }
- }
- if (purgeReadBuffers)
- {
- int result = mConnection.ControlTransfer((UsbAddressing)REQTYPE_HOST_TO_DEVICE, RESET_REQUEST,
- RESET_PURGE_RX, mPortNumber + 1, null, 0, USB_WRITE_TIMEOUT_MILLIS);
- if (result != 0)
- {
- throw new IOException("Flushing RX failed: result=" + result);
- }
- }
-
- return true;
- }
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_FTDI, new int[]
- {
- UsbId.FTDI_FT232R,
- UsbId.FTDI_FT232H,
- UsbId.FTDI_FT2232H,
- UsbId.FTDI_FT4232H,
- UsbId.FTDI_FT231X, // same ID for FT230X, FT231X, FT234XD
- }
- }
- };
- }
- }
-}
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Parity.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Parity.cs
deleted file mode 100644
index a8db406..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/Parity.cs
+++ /dev/null
@@ -1,26 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public enum Parity
- {
- None = 0,
- Odd = 1,
- Even = 2,
- Mark = 3,
- Space = 4,
- NotSet = -1
- }
- public enum StopBits
- {
- One = 1,
- OnePointFive = 3,
- Two = 2,
- NotSet = -1
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProbeTable.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProbeTable.cs
deleted file mode 100644
index bd5e710..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProbeTable.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.Reflection;
-using Android.Util;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class ProbeTable
- {
- private readonly string TAG = typeof(ProbeTable).Name;
-
- Dictionary, Type> mProbeTable = new Dictionary, Type>();
-
-
- /**
- * Adds or updates a (vendor, product) pair in the table.
- *
- * @param vendorId the USB vendor id
- * @param productId the USB product id
- * @param driverClass the driver class responsible for this pair
- * @return {@code this}, for chaining
- */
- public ProbeTable AddProduct(int vendorId, int productId,
- Type driverClass)
- {
- var key = new Tuple(vendorId, productId);
-
- if (!mProbeTable.ContainsKey(key))
- mProbeTable.Add(key, driverClass);
-
- return this;
- }
-
- public ProbeTable AddDriver(Type driverClass)
- {
- MethodInfo m = driverClass.GetMethod("GetSupportedDevices");
-
- var devices = (Dictionary)m.Invoke(null, null);
-
- foreach (var vendorId in devices.Keys)
- {
- var productIds = devices[vendorId];
-
- foreach (var productId in productIds)
- {
- try
- {
- AddProduct(vendorId, productId, driverClass);
- Log.Debug(TAG, $"Added {vendorId:X}, {productId:X}, {driverClass}");
- }
- catch (Exception)
- {
- Log.Debug(TAG, $"Error adding {vendorId:X}, {productId:X}, {driverClass}");
-
- throw;
- }
- }
- }
-
- return this;
-
- }
-
- public Type FindDriver(int vendorId, int productId)
- {
- var pair = new Tuple(vendorId, productId);
-
- return mProbeTable.ContainsKey(pair) ? mProbeTable[pair] : null;
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProlificSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProlificSerialDriver.cs
deleted file mode 100644
index 55f28ab..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/ProlificSerialDriver.cs
+++ /dev/null
@@ -1,659 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using Android.Hardware.Usb;
-using Android.Util;
-using Java.Lang;
-using Boolean = System.Boolean;
-using Exception = Java.Lang.Exception;
-using Object = System.Object;
-using Thread = System.Threading.Thread;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class ProlificSerialDriver : UsbSerialDriver
- {
- private readonly string TAG = typeof(ProlificSerialDriver).Name;
-
- public ProlificSerialDriver(UsbDevice device)
- {
- mDevice = device;
- mPort = new ProlificSerialPort(mDevice, 0, this);
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_PROLIFIC, new int[]
- {
- UsbId.PROLIFIC_PL2303,
- UsbId.PROLIFIC_PL2303GC,
- UsbId.PROLIFIC_PL2303GB,
- UsbId.PROLIFIC_PL2303GT,
- UsbId.PROLIFIC_PL2303GL,
- UsbId.PROLIFIC_PL2303GE,
- UsbId.PROLIFIC_PL2303GS
-
- }
- }
- };
- }
-
-
- class ProlificSerialPort : CommonUsbSerialPort
- {
- protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN }
-
- private static int USB_READ_TIMEOUT_MILLIS = 1000;
- private static int USB_WRITE_TIMEOUT_MILLIS = 5000;
-
- private static int USB_RECIP_INTERFACE = 0x01;
-
- private static int VENDOR_READ_REQUEST = 0x01;
- private static int VENDOR_WRITE_REQUEST = 0x01;
- private static int VENDOR_READ_HXN_REQUEST = 0x81;
- private static int VENDOR_WRITE_HXN_REQUEST = 0x80;
-
- private static int VENDOR_OUT_REQTYPE = UsbSupport.UsbDirOut | UsbConstants.UsbTypeVendor;
- private static int VENDOR_IN_REQTYPE = UsbSupport.UsbDirIn | UsbConstants.UsbTypeVendor;
- private static int CTRL_OUT_REQTYPE = UsbSupport.UsbDirOut | UsbConstants.UsbTypeClass | USB_RECIP_INTERFACE;
-
- private const int WRITE_ENDPOINT = 0x02;
- private const int READ_ENDPOINT = 0x83;
- private const int INTERRUPT_ENDPOINT = 0x81;
-
- private static int RESET_HXN_REQUEST = 0x07;
- private static int FLUSH_RX_REQUEST = 0x08;
- private static int FLUSH_TX_REQUEST = 0x09;
-
- private static int SET_LINE_REQUEST = 0x20; // same as CDC SET_LINE_CODING
- private static int SET_CONTROL_REQUEST = 0x22; // same as CDC SET_CONTROL_LINE_STATE
- private static int SEND_BREAK_REQUEST = 0x23; // same as CDC SEND_BREAK
- private static int GET_CONTROL_HXN_REQUEST = 0x80;
- private static int GET_CONTROL_REQUEST = 0x87;
- private static int STATUS_NOTIFICATION = 0xa1; // similar to CDC SERIAL_STATE but different length
-
- /* RESET_HXN_REQUEST */
- private static int RESET_HXN_RX_PIPE = 1;
- private static int RESET_HXN_TX_PIPE = 2;
-
- /* SET_CONTROL_REQUEST */
- private static int CONTROL_DTR = 0x01;
- private static int CONTROL_RTS = 0x02;
-
- /* GET_CONTROL_REQUEST */
- private static int GET_CONTROL_FLAG_CD = 0x02;
- private static int GET_CONTROL_FLAG_DSR = 0x04;
- private static int GET_CONTROL_FLAG_RI = 0x01;
- private static int GET_CONTROL_FLAG_CTS = 0x08;
-
- /* GET_CONTROL_HXN_REQUEST */
- private static int GET_CONTROL_HXN_FLAG_CD = 0x40;
- private static int GET_CONTROL_HXN_FLAG_DSR = 0x20;
- private static int GET_CONTROL_HXN_FLAG_RI = 0x80;
- private static int GET_CONTROL_HXN_FLAG_CTS = 0x08;
-
- /* interrupt endpoint read */
- private static int STATUS_FLAG_CD = 0x01;
- private static int STATUS_FLAG_DSR = 0x02;
- private static int STATUS_FLAG_RI = 0x08;
- private static int STATUS_FLAG_CTS = 0x80;
-
- private static int STATUS_BUFFER_SIZE = 10;
- private static int STATUS_BYTE_IDX = 8;
-
- private DeviceType mDeviceType = DeviceType.DEVICE_TYPE_HX;
-
- private UsbEndpoint mReadEndpoint;
- private UsbEndpoint mWriteEndpoint;
- private UsbEndpoint mInterruptEndpoint;
-
- private int mControlLinesValue = 0;
-
- private int mBaudRate = -1, mDataBits = -1;
- private StopBits mStopBits = StopBits.NotSet;
- private Parity mParity = Parity.NotSet;
-
- private int mStatus = 0;
- private volatile Thread mReadStatusThread = null;
- private Object mReadStatusThreadLock = new Object();
- Boolean mStopReadStatusThread = false;
- private IOException mReadStatusException = null;
-
- private IUsbSerialDriver Driver;
-
- private string TAG => (Driver as ProlificSerialDriver)?.TAG;
-
- public ProlificSerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver)
- : base(device, portNumber)
- {
- Driver = driver;
- }
-
- public override IUsbSerialDriver GetDriver()
- {
- return Driver;
- }
-
- private byte[] InControlTransfer(int requestType, int request,
- int value, int index, int length)
- {
- byte[] buffer = new byte[length];
- int result = mConnection.ControlTransfer((UsbAddressing)requestType, request, value,
- index, buffer, length, USB_READ_TIMEOUT_MILLIS);
- if (result != length)
- {
- throw new IOException($"ControlTransfer with value {value} failed: {result}");
- }
- return buffer;
- }
-
- private void OutControlTransfer(int requestType, int request,
- int value, int index, byte[] data)
- {
- int length = data?.Length ?? 0;
- int result = mConnection.ControlTransfer((UsbAddressing)requestType, request, value,
- index, data, length, USB_WRITE_TIMEOUT_MILLIS);
- if (result != length)
- {
- throw new IOException($"ControlTransfer with value {value} failed: {result}");
- }
- }
-
- private byte[] VendorIn(int value, int index, int length)
- {
- int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_READ_HXN_REQUEST : VENDOR_READ_REQUEST;
- return InControlTransfer(VENDOR_IN_REQTYPE, request, value, index, length);
- }
-
- private void VendorOut(int value, int index, byte[] data)
- {
- int request = (mDeviceType == DeviceType.DEVICE_TYPE_HXN) ? VENDOR_WRITE_HXN_REQUEST : VENDOR_WRITE_REQUEST;
- OutControlTransfer(VENDOR_OUT_REQTYPE, request, value, index, data);
- }
-
- private void ResetDevice()
- {
- PurgeHwBuffers(true, true);
- }
-
- private void CtrlOut(int request, int value, int index, byte[] data)
- {
- OutControlTransfer(CTRL_OUT_REQTYPE, request, value, index, data);
- }
-
- private Boolean TestHxStatus()
- {
- try
- {
- InControlTransfer(VENDOR_IN_REQTYPE, VENDOR_READ_REQUEST, 0x8080, 0, 1);
- return true;
- }
- catch (IOException ignored)
- {
- return false;
- }
- }
-
- private void DoBlackMagic()
- {
- if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
- return;
-
- VendorIn(0x8484, 0, 1);
- VendorOut(0x0404, 0, null);
- VendorIn(0x8484, 0, 1);
- VendorIn(0x8383, 0, 1);
- VendorIn(0x8484, 0, 1);
- VendorOut(0x0404, 1, null);
- VendorIn(0x8484, 0, 1);
- VendorIn(0x8383, 0, 1);
- VendorOut(0, 1, null);
- VendorOut(1, 0, null);
- VendorOut(2, (mDeviceType == DeviceType.DEVICE_TYPE_HX) ? 0x44 : 0x24, null);
- }
-
- private void SetControlLines(int newControlLinesValue)
- {
- CtrlOut(SET_CONTROL_REQUEST, newControlLinesValue, 0, null);
- mControlLinesValue = newControlLinesValue;
- }
-
- private void ReadStatusThreadFunction()
- {
- try
- {
- while (!mStopReadStatusThread)
- {
- byte[] buffer = new byte[STATUS_BUFFER_SIZE];
- int readBytesCount = mConnection.BulkTransfer(mInterruptEndpoint,
- buffer,
- STATUS_BUFFER_SIZE,
- 500);
- if (readBytesCount > 0)
- {
- if (readBytesCount == STATUS_BUFFER_SIZE)
- {
- mStatus = buffer[STATUS_BYTE_IDX] & 0xff;
- }
- else
- {
- throw new IOException(
- $"Invalid CTS / DSR / CD / RI status buffer received, expected {STATUS_BUFFER_SIZE} bytes, but received {readBytesCount}");
- }
- }
- }
- }
- catch (IOException e)
- {
- mReadStatusException = e;
- }
- }
-
- private int GetStatus()
- {
- if ((mReadStatusThread == null) && (mReadStatusException == null))
- {
- lock (mReadStatusThreadLock)
- {
- if (mReadStatusThread == null)
- {
- mStatus = 0;
- if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
- {
- byte[] data = VendorIn(GET_CONTROL_HXN_REQUEST, 0, 1);
- if ((data[0] & GET_CONTROL_HXN_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
- if ((data[0] & GET_CONTROL_HXN_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
- if ((data[0] & GET_CONTROL_HXN_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
- if ((data[0] & GET_CONTROL_HXN_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
- }
- else
- {
- byte[] data = VendorIn(GET_CONTROL_REQUEST, 0, 1);
- if ((data[0] & GET_CONTROL_FLAG_CTS) == 0) mStatus |= STATUS_FLAG_CTS;
- if ((data[0] & GET_CONTROL_FLAG_DSR) == 0) mStatus |= STATUS_FLAG_DSR;
- if ((data[0] & GET_CONTROL_FLAG_CD) == 0) mStatus |= STATUS_FLAG_CD;
- if ((data[0] & GET_CONTROL_FLAG_RI) == 0) mStatus |= STATUS_FLAG_RI;
- }
- ThreadStart mReadStatusThreadDelegate = new ThreadStart(ReadStatusThreadFunction);
-
- mReadStatusThread = new Thread(mReadStatusThreadDelegate);
-
- mReadStatusThread.Start();
-
- //mReadStatusThread = new Thread(new Runnable()
- //{
- // public void run()
- // {
- // ReadStatusThreadFunction();
- // }
- //});
- //mReadStatusThread.Daemon = true;// setDaemon(true);
- //mReadStatusThread.Start();
- }
- }
- }
-
-
- /* throw and clear an exception which occured in the status read thread */
- IOException readStatusException = mReadStatusException;
- if (mReadStatusException != null)
- {
- mReadStatusException = null;
- throw readStatusException;
- }
-
- return mStatus;
- }
-
- private Boolean TestStatusFlag(int flag)
- {
- return ((GetStatus() & flag) == flag);
- }
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null)
- {
- throw new IOException("Already open");
- }
-
- UsbInterface usbInterface = mDevice.GetInterface(0);
-
- if (!connection.ClaimInterface(usbInterface, true))
- {
- throw new IOException("Error claiming Prolific interface 0");
- }
- mConnection = connection;
- Boolean opened = false;
- try
- {
- for (int i = 0; i < usbInterface.EndpointCount; ++i)
- {
- UsbEndpoint currentEndpoint = usbInterface.GetEndpoint(i);
-
- switch (currentEndpoint.Address)
- {
- case (UsbAddressing)READ_ENDPOINT:
- mReadEndpoint = currentEndpoint;
- break;
-
- case (UsbAddressing)WRITE_ENDPOINT:
- mWriteEndpoint = currentEndpoint;
- break;
-
- case (UsbAddressing)INTERRUPT_ENDPOINT:
- mInterruptEndpoint = currentEndpoint;
- break;
- }
- }
-
- byte[] rawDescriptors = connection.GetRawDescriptors();
- if (rawDescriptors == null || rawDescriptors.Length < 14)
- {
- throw new IOException("Could not get device descriptors");
- }
- int usbVersion = (rawDescriptors[3] << 8) + rawDescriptors[2];
- int deviceVersion = (rawDescriptors[13] << 8) + rawDescriptors[12];
- byte maxPacketSize0 = rawDescriptors[7];
-
- if (mDevice.DeviceClass == UsbClass.Comm || maxPacketSize0 != 64)
- {
- mDeviceType = DeviceType.DEVICE_TYPE_01;
- }
- else if (deviceVersion == 0x300 && usbVersion == 0x200)
- {
- mDeviceType = DeviceType.DEVICE_TYPE_T; // TA
- }
- else if (deviceVersion == 0x500)
- {
- mDeviceType = DeviceType.DEVICE_TYPE_T; // TB
- }
- else if (usbVersion == 0x200 && !TestHxStatus())
- {
- mDeviceType = DeviceType.DEVICE_TYPE_HXN;
- }
- else
- {
- mDeviceType = DeviceType.DEVICE_TYPE_HX;
- }
-
- SetControlLines(mControlLinesValue);
- ResetDevice();
-
- DoBlackMagic();
- opened = true;
- }
- finally
- {
- if (!opened)
- {
- mConnection = null;
- connection.ReleaseInterface(usbInterface);
- }
- }
- }
-
- public override void Close()
- {
- if (mConnection == null)
- {
- throw new IOException("Already closed");
- }
- try
- {
- mStopReadStatusThread = true;
- lock (mReadStatusThreadLock)
- {
- if (mReadStatusThread != null)
- {
- try
- {
- mReadStatusThread.Join();
- }
- catch (Exception e)
- {
- Log.Warn(TAG, "An error occured while waiting for status read thread", e);
- }
- }
- }
- ResetDevice();
- }
- finally
- {
- try
- {
- mConnection.ReleaseInterface(mDevice.GetInterface(0));
- }
- finally
- {
- mConnection = null;
- }
- }
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- lock (mReadBufferLock)
- {
- int readAmt = System.Math.Min(dest.Length, mReadBuffer.Length);
- int numBytesRead = mConnection.BulkTransfer(mReadEndpoint, mReadBuffer,
- readAmt, timeoutMillis);
- if (numBytesRead < 0)
- {
- return 0;
- }
- Buffer.BlockCopy(mReadBuffer, 0, dest, 0, numBytesRead);
- return numBytesRead;
- }
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- int offset = 0;
-
- while (offset < src.Length)
- {
- int writeLength;
- int amtWritten;
-
- lock (mWriteBufferLock)
- {
- byte[] writeBuffer;
-
- writeLength = System.Math.Min(src.Length - offset, mWriteBuffer.Length);
- if (offset == 0)
- {
- writeBuffer = src;
- }
- else
- {
- // bulkTransfer does not support offsets, make a copy.
- Buffer.BlockCopy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
- }
-
- amtWritten = mConnection.BulkTransfer(mWriteEndpoint,
- writeBuffer, writeLength, timeoutMillis);
- }
-
- if (amtWritten <= 0)
- {
- throw new IOException(
- $"Error writing {writeLength} bytes at offset {offset} length={src.Length}");
- }
-
- offset += amtWritten;
- }
- return offset;
- }
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- if ((mBaudRate == baudRate) && (mDataBits == dataBits)
- && (mStopBits == stopBits) && (mParity == parity))
- {
- // Make sure no action is performed if there is nothing to change
- return;
- }
-
- byte[] lineRequestData = new byte[7];
-
- lineRequestData[0] = (byte)(baudRate & 0xff);
- lineRequestData[1] = (byte)((baudRate >> 8) & 0xff);
- lineRequestData[2] = (byte)((baudRate >> 16) & 0xff);
- lineRequestData[3] = (byte)((baudRate >> 24) & 0xff);
-
- switch (stopBits)
- {
- case StopBits.One:
- lineRequestData[4] = 0;
- break;
-
- case StopBits.OnePointFive:
- lineRequestData[4] = 1;
- break;
-
- case StopBits.Two:
- lineRequestData[4] = 2;
- break;
-
- default:
- throw new IllegalArgumentException("Unknown stopBits value: " + stopBits);
- }
-
- switch (parity)
- {
- case Parity.None:
- lineRequestData[5] = 0;
- break;
-
- case Parity.Odd:
- lineRequestData[5] = 1;
- break;
-
- case Parity.Even:
- lineRequestData[5] = 2;
- break;
-
- case Parity.Mark:
- lineRequestData[5] = 3;
- break;
-
- case Parity.Space:
- lineRequestData[5] = 4;
- break;
-
- default:
- throw new IllegalArgumentException("Unknown parity value: " + parity);
- }
-
- lineRequestData[6] = (byte)dataBits;
-
- CtrlOut(SET_LINE_REQUEST, 0, 0, lineRequestData);
-
- ResetDevice();
-
- mBaudRate = baudRate;
- mDataBits = dataBits;
- mStopBits = stopBits;
- mParity = parity;
- }
-
- public override Boolean GetCD()
- {
- return TestStatusFlag(STATUS_FLAG_CD);
- }
-
-
- public override Boolean GetCTS()
- {
- return TestStatusFlag(STATUS_FLAG_CTS);
- }
-
-
- public override Boolean GetDSR()
- {
- return TestStatusFlag(STATUS_FLAG_DSR);
- }
-
-
- public override Boolean GetDTR()
- {
- return ((mControlLinesValue & CONTROL_DTR) == CONTROL_DTR);
- }
-
-
- public override void SetDTR(Boolean value)
- {
- int newControlLinesValue;
- if (value)
- {
- newControlLinesValue = mControlLinesValue | CONTROL_DTR;
- }
- else
- {
- newControlLinesValue = mControlLinesValue & ~CONTROL_DTR;
- }
- SetControlLines(newControlLinesValue);
- }
-
-
- public override Boolean GetRI()
- {
- return TestStatusFlag(STATUS_FLAG_RI);
- }
-
-
- public override Boolean GetRTS()
- {
- return ((mControlLinesValue & CONTROL_RTS) == CONTROL_RTS);
- }
-
-
- public override void SetRTS(Boolean value)
- {
- int newControlLinesValue;
- if (value)
- {
- newControlLinesValue = mControlLinesValue | CONTROL_RTS;
- }
- else
- {
- newControlLinesValue = mControlLinesValue & ~CONTROL_RTS;
- }
- SetControlLines(newControlLinesValue);
- }
-
- public override Boolean PurgeHwBuffers(Boolean purgeReadBuffers, Boolean purgeWriteBuffers)
- {
- if (mDeviceType == DeviceType.DEVICE_TYPE_HXN)
- {
- int index = 0;
- if (purgeWriteBuffers) index |= RESET_HXN_RX_PIPE;
- if (purgeReadBuffers) index |= RESET_HXN_TX_PIPE;
- if (index != 0)
- VendorOut(RESET_HXN_REQUEST, index, null);
- }
- else
- {
- if (purgeWriteBuffers)
- VendorOut(FLUSH_RX_REQUEST, 0, null);
- if (purgeReadBuffers)
- VendorOut(FLUSH_TX_REQUEST, 0, null);
- }
- return purgeReadBuffers || purgeWriteBuffers;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/STM32SerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/STM32SerialDriver.cs
deleted file mode 100644
index 9ed94c1..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/STM32SerialDriver.cs
+++ /dev/null
@@ -1,309 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using System.IO;
-using Android.Hardware.Usb;
-using Android.Util;
-using Java.Nio;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class STM32SerialDriver : UsbSerialDriver
- {
- readonly string TAG = nameof(STM32SerialDriver);
-
- int mCtrlInterf;
-
- public STM32SerialDriver(UsbDevice device)
- {
- mDevice = device;
- mPort = new STM32SerialPort(mDevice, 0, this);
- }
-
- public class STM32SerialPort : CommonUsbSerialPort
- {
- readonly string TAG = nameof(STM32SerialDriver);
-
- readonly bool ENABLE_ASYNC_READS;
- UsbInterface mControlInterface;
- UsbInterface mDataInterface;
-
- UsbEndpoint mReadEndpoint;
- UsbEndpoint mWriteEndpoint;
-
- bool mRts = false;
- bool mDtr = false;
-
- IUsbSerialDriver Driver;
-
- const int USB_WRITE_TIMEOUT_MILLIS = 5000;
-
- const int USB_RECIP_INTERFACE = 0x01;
- const int USB_RT_AM = UsbConstants.UsbTypeClass | USB_RECIP_INTERFACE;
-
- const int SET_LINE_CODING = 0x20; // USB CDC 1.1 section 6.2
- const int SET_CONTROL_LINE_STATE = 0x22;
-
- public STM32SerialPort(UsbDevice device, int portNumber, IUsbSerialDriver driver) : base(device, portNumber)
- {
- Driver = driver;
- ENABLE_ASYNC_READS = true;
- }
-
- public override IUsbSerialDriver GetDriver() =>
- Driver;
-
- int SendAcmControlMessage(int request, int value, byte[] buf) =>
- mConnection.ControlTransfer((UsbAddressing)USB_RT_AM, request, value, (Driver as STM32SerialDriver).mCtrlInterf, buf, buf?.Length ?? 0, USB_WRITE_TIMEOUT_MILLIS);
-
- public override void Open(UsbDeviceConnection connection)
- {
- if (mConnection != null)
- throw new IOException("Already opened.");
-
- mConnection = connection;
- bool opened = false;
- bool controlInterfaceFound = false;
- try
- {
- for (var i = 0; i < mDevice.InterfaceCount; i++)
- {
- mControlInterface = mDevice.GetInterface(i);
- if(mControlInterface.InterfaceClass == UsbClass.Comm)
- {
- if (!mConnection.ClaimInterface(mControlInterface, true))
- throw new IOException("Could not claim control interface");
- (Driver as STM32SerialDriver).mCtrlInterf = i;
- controlInterfaceFound = true;
- break;
- }
- }
- if (!controlInterfaceFound)
- throw new IOException("Could not claim control interface");
- for (var i = 0; i < mDevice.InterfaceCount; i++)
- {
- mDataInterface = mDevice.GetInterface(i);
- if(mDataInterface.InterfaceClass == UsbClass.CdcData)
- {
- if (!mConnection.ClaimInterface(mDataInterface, true))
- throw new IOException("Could not claim data interface");
- mReadEndpoint = mDataInterface.GetEndpoint(1);
- mWriteEndpoint = mDataInterface.GetEndpoint(0);
- opened = true;
- break;
- }
- }
- if(!opened)
- throw new IOException("Could not claim data interface.");
- }
- finally
- {
- if (!opened)
- mConnection = null;
- }
- }
-
- public override void Close()
- {
- if (mConnection == null)
- throw new IOException("Already closed");
- mConnection.Close();
- mConnection = null;
- }
-
- public override int Read(byte[] dest, int timeoutMillis)
- {
- if(ENABLE_ASYNC_READS)
- {
- var request = new UsbRequest();
- try
- {
- request.Initialize(mConnection, mReadEndpoint);
- ByteBuffer buf = ByteBuffer.Wrap(dest);
- if (!request.Queue(buf, dest.Length))
- throw new IOException("Error queuing request");
-
- UsbRequest response = mConnection.RequestWait();
- if (response == null)
- throw new IOException("Null response");
-
- int nread = buf.Position();
- if (nread > 0)
- return nread;
-
- return 0;
- }
- finally
- {
- request.Close();
- }
- }
-
- int numBytesRead;
- lock(mReadBufferLock)
- {
- int readAmt = Math.Min(dest.Length, mReadBuffer.Length);
- numBytesRead = mConnection.BulkTransfer(mReadEndpoint, mReadBuffer, readAmt, timeoutMillis);
- if(numBytesRead < 0)
- {
- // This sucks: we get -1 on timeout, not 0 as preferred.
- // We *should* use UsbRequest, except it has a bug/api oversight
- // where there is no way to determine the number of bytes read
- // in response :\ -- http://b.android.com/28023
- if (timeoutMillis == int.MaxValue)
- {
- // Hack: Special case "~infinite timeout" as an error.
- return -1;
- }
-
- return 0;
- }
- Array.Copy(mReadBuffer, 0, dest, 0, numBytesRead);
- }
- return numBytesRead;
- }
-
- public override int Write(byte[] src, int timeoutMillis)
- {
- int offset = 0;
-
- while(offset < src.Length)
- {
- int writeLength;
- int amtWritten;
-
- lock(mWriteBufferLock)
- {
- byte[] writeBuffer;
-
- writeLength = Math.Min(src.Length - offset, mWriteBuffer.Length);
- if (offset == 0)
- writeBuffer = src;
- else
- {
- Array.Copy(src, offset, mWriteBuffer, 0, writeLength);
- writeBuffer = mWriteBuffer;
- }
-
- amtWritten = mConnection.BulkTransfer(mWriteEndpoint, writeBuffer, writeLength, timeoutMillis);
- }
- if(amtWritten <= 0)
- throw new IOException($"Error writing {writeLength} bytes at offset {offset} length={src.Length}");
-
- Log.Debug(TAG, $"Wrote amt={amtWritten} attempted={writeLength}");
- offset += amtWritten;
- }
-
- return offset;
- }
-
- public override void SetParameters(int baudRate, int dataBits, StopBits stopBits, Parity parity)
- {
- byte stopBitsBytes;
- switch(stopBits)
- {
- case StopBits.One:
- stopBitsBytes = 0;
- break;
- case StopBits.OnePointFive:
- stopBitsBytes = 1;
- break;
- case StopBits.Two:
- stopBitsBytes = 2;
- break;
- default:
- throw new ArgumentException($"Bad value for stopBits: {stopBits}");
- }
-
- byte parityBitesBytes;
- switch(parity)
- {
- case Parity.None:
- parityBitesBytes = 0;
- break;
- case Parity.Odd:
- parityBitesBytes = 1;
- break;
- case Parity.Even:
- parityBitesBytes = 2;
- break;
- case Parity.Mark:
- parityBitesBytes = 3;
- break;
- case Parity.Space:
- parityBitesBytes = 4;
- break;
- default:
- throw new ArgumentException($"Bad value for parity: {parity}");
- }
-
- byte[] msg = {
- (byte)(baudRate & 0xff),
- (byte) ((baudRate >> 8 ) & 0xff),
- (byte) ((baudRate >> 16) & 0xff),
- (byte) ((baudRate >> 24) & 0xff),
- stopBitsBytes,
- parityBitesBytes,
- (byte) dataBits
- };
- SendAcmControlMessage(SET_LINE_CODING, 0, msg);
- }
-
- public override bool GetCD() =>
- false; //TODO
-
- public override bool GetCTS() =>
- false; //TODO
-
- public override bool GetDSR() =>
- false; // TODO
-
- public override bool GetDTR() =>
- mDtr;
-
- public override void SetDTR(bool value)
- {
- mDtr = value;
- SetDtrRts();
- }
-
- public override bool GetRI() =>
- false; //TODO
-
- public override bool GetRTS() =>
- mRts; //TODO
-
- public override void SetRTS(bool value)
- {
- mRts = value;
- SetDtrRts();
- }
-
- void SetDtrRts()
- {
- int value = (mRts ? 0x2 : 0) | (mDtr ? 0x1 : 0);
- SendAcmControlMessage(SET_CONTROL_LINE_STATE, value, null);
- }
-
- public static Dictionary GetSupportedDevices()
- {
- return new Dictionary
- {
- {
- UsbId.VENDOR_STM, new int[]
- {
- UsbId.STM32_STLINK,
- UsbId.STM32_VCOM
- }
- }
- };
- }
- }
- }
-}
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbId.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbId.cs
deleted file mode 100644
index 0064462..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbId.cs
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-namespace Hoho.Android.UsbSerial.driver
-{
- /**
- * Registry of USB vendor/product ID constants.
- *
- * Culled from various sources; see
- * usb.ids for one listing.
- *
- * @author mike wakerly (opensource@hoho.com)
- */
- public static class UsbId
- {
- public static readonly int VENDOR_FTDI = 0x0403;
- public static readonly int FTDI_FT232R = 0x6001;
- public static readonly int FTDI_FT2232H = 0x6010;
- public static readonly int FTDI_FT4232H = 0x6011;
- public static readonly int FTDI_FT232H = 0x6014;
- public static readonly int FTDI_FT231X = 0x6015; // same ID for FT230X, FT231X, FT234XD
-
-
- public static readonly int VENDOR_ATMEL = 0x03EB;
- public static readonly int ATMEL_LUFA_CDC_DEMO_APP = 0x2044;
-
- public static readonly int VENDOR_ARDUINO = 0x2341;
- public static readonly int ARDUINO_UNO = 0x0001;
- public static readonly int ARDUINO_MEGA_2560 = 0x0010;
- public static readonly int ARDUINO_SERIAL_ADAPTER = 0x003b;
- public static readonly int ARDUINO_MEGA_ADK = 0x003f;
- public static readonly int ARDUINO_MEGA_2560_R3 = 0x0042;
- public static readonly int ARDUINO_UNO_R3 = 0x0043;
- public static readonly int ARDUINO_MEGA_ADK_R3 = 0x0044;
- public static readonly int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044;
- public static readonly int ARDUINO_LEONARDO = 0x8036;
- public static readonly int ARDUINO_MICRO = 0x8037;
-
- public static readonly int VENDOR_VAN_OOIJEN_TECH = 0x16c0;
- public static readonly int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483;
-
- public static readonly int VENDOR_LEAFLABS = 0x1eaf;
- public static readonly int LEAFLABS_MAPLE = 0x0004;
-
- public static readonly int VENDOR_SILABS = 0x10c4;
- public static readonly int SILABS_CP2102 = 0xea60;
- public static readonly int SILABS_CP2105 = 0xea70;
- public static readonly int SILABS_CP2108 = 0xea71;
- public static readonly int SILABS_CP2110 = 0xea80;
-
- public static readonly int VENDOR_PROLIFIC = 0x067b;
- public static readonly int PROLIFIC_PL2303 = 0x2303;
- public static readonly int PROLIFIC_PL2303GC = 0x23a3; // device type HXN
- public static readonly int PROLIFIC_PL2303GB = 0x23b3; // "
- public static readonly int PROLIFIC_PL2303GT = 0x23c3; // "
- public static readonly int PROLIFIC_PL2303GL = 0x23d3; // "
- public static readonly int PROLIFIC_PL2303GE = 0x23e3; // "
- public static readonly int PROLIFIC_PL2303GS = 0x23f3; // "
-
- public static readonly int VENDOR_QINHENG = 0x1a86;
- public static readonly int QINHENG_HL340 = 0x7523;
- public static readonly int QINHENG_CH341A = 0x5523;
-
- public static readonly int VENDOR_ELATEC = 0x09D8;
- public static readonly int ELATEC_TWN3_KEYBOARD = 0x0310; // Not needed
- public static readonly int ELATEC_TWN3_CDC = 0x0320;
- public static readonly int ELATEC_TWN4_MIFARE_NFC = 0x0406; // One off for an Elatec customer
- public static readonly int ELATEC_TWN4_KEYBOARD = 0x0410; // Not needed
- public static readonly int ELATEC_TWN4_CDC = 0x0420;
- public static readonly int ELATEC_TWN4_SC_READER = 0x0428; // Uses CCID protocol, not serial
-
- // at www.linux-usb.org/usb.ids listed for NXP/LPC1768, but all processors supported by ARM mbed DAPLink firmware report these ids
- public static readonly int VENDOR_ARM = 0x0d28;
- public static readonly int ARM_MBED = 0x0204;
-
- public static readonly int VENDOR_STM = 0x0483;
- public static readonly int STM32_STLINK = 0x374B;
- public static readonly int STM32_VCOM = 0x5740;
-
- public static readonly int VENDOR_RASPBERRY_PI = 0x2e8a;
- public static readonly int RASPBERRY_PI_PICO_MICROPYTHON = 0x0005;
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialDriver.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialDriver.cs
deleted file mode 100644
index c356fa5..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialDriver.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System.Collections.Generic;
-using Android.Hardware.Usb;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public interface IUsbSerialDriver
- {
- UsbDevice Device { get; }
-
- UsbDevice GetDevice();
-
- List Ports { get; }
- List GetPorts();
-
- //Dictionary GetSupportedDevices();
- }
- public class UsbSerialDriver : IUsbSerialDriver
- {
- protected UsbDevice mDevice;
- protected UsbSerialPort mPort;
- public UsbDevice Device => GetDevice();
-
- public List Ports => GetPorts();
-
- public UsbDevice GetDevice()
- {
- return mDevice;
- }
-
- public virtual List GetPorts()
- {
- return new List { mPort };
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialPort.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialPort.cs
deleted file mode 100644
index 628f9bd..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialPort.cs
+++ /dev/null
@@ -1,209 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using Android.Hardware.Usb;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public abstract class UsbSerialPort
- {
- /** 5 data bits. */
- public const int DATABITS_5 = 5;
-
- /** 6 data bits. */
- public const int DATABITS_6 = 6;
-
- /** 7 data bits. */
- public const int DATABITS_7 = 7;
-
- /** 8 data bits. */
- public const int DATABITS_8 = 8;
-
- /** No flow control. */
- public const int FLOWCONTROL_NONE = 0;
-
- /** RTS/CTS input flow control. */
- public const int FLOWCONTROL_RTSCTS_IN = 1;
-
- /** RTS/CTS output flow control. */
- public const int FLOWCONTROL_RTSCTS_OUT = 2;
-
- /** XON/XOFF input flow control. */
- public const int FLOWCONTROL_XONXOFF_IN = 4;
-
- /** XON/XOFF output flow control. */
- public const int FLOWCONTROL_XONXOFF_OUT = 8;
-
- /** No parity. */
- public const int PARITY_NONE = 0;
-
- /** Odd parity. */
- public const int PARITY_ODD = 1;
-
- /** Even parity. */
- public const int PARITY_EVEN = 2;
-
- /** Mark parity. */
- public const int PARITY_MARK = 3;
-
- /** Space parity. */
- public const int PARITY_SPACE = 4;
-
- /** 1 stop bit. */
- public const int STOPBITS_1 = 1;
-
- /** 1.5 stop bits. */
- public const int STOPBITS_1_5 = 3;
-
- /** 2 stop bits. */
- public const int STOPBITS_2 = 2;
-
- public IUsbSerialDriver Driver => GetDriver();
-
- public abstract IUsbSerialDriver GetDriver();
-
- /**
- * Port number within driver.
- */
- public int PortNumber => GetPortNumber();
- public abstract int GetPortNumber();
-
- /**
- * The serial number of the underlying UsbDeviceConnection, or {@code null}.
- */
- public abstract string GetSerial();
-
- /**
- * Opens and initializes the port. Upon success, caller must ensure that
- * {@link #close()} is eventually called.
- *
- * @param connection an open device connection, acquired with
- * {@link UsbManager#openDevice(android.hardware.usb.UsbDevice)}
- * @throws IOException on error opening or initializing the port.
- */
- public abstract void Open(UsbDeviceConnection connection);
-
- /**
- * Closes the port.
- *
- * @throws IOException on error closing the port.
- */
- public abstract void Close();
-
- /**
- * Reads as many bytes as possible into the destination buffer.
- *
- * @param dest the destination byte buffer
- * @param timeoutMillis the timeout for reading
- * @return the actual number of bytes read
- * @throws IOException if an error occurred during reading
- */
- public abstract int Read(byte[] dest, int timeoutMillis);
-
- /**
- * Writes as many bytes as possible from the source buffer.
- *
- * @param src the source byte buffer
- * @param timeoutMillis the timeout for writing
- * @return the actual number of bytes written
- * @throws IOException if an error occurred during writing
- */
- public abstract int Write(byte[] src, int timeoutMillis);
-
- /**
- * Sets various serial port parameters.
- *
- * @param baudRate baud rate as an integer, for example {@code 115200}.
- * @param dataBits one of {@link #DATABITS_5}, {@link #DATABITS_6},
- * {@link #DATABITS_7}, or {@link #DATABITS_8}.
- * @param stopBits one of {@link #STOPBITS_1}, {@link #STOPBITS_1_5}, or
- * {@link #STOPBITS_2}.
- * @param parity one of {@link #PARITY_NONE}, {@link #PARITY_ODD},
- * {@link #PARITY_EVEN}, {@link #PARITY_MARK}, or
- * {@link #PARITY_SPACE}.
- * @throws IOException on error setting the port parameters
- */
- public abstract void SetParameters(
- int baudRate, int dataBits, StopBits stopBits, Parity parity);
-
- /**
- * Gets the CD (Carrier Detect) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetCD();
-
- /**
- * Gets the CTS (Clear To Send) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetCTS();
-
- /**
- * Gets the DSR (Data Set Ready) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetDSR();
-
- /**
- * Gets the DTR (Data Terminal Ready) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetDTR();
-
- /**
- * Sets the DTR (Data Terminal Ready) bit on the underlying UART, if
- * supported.
- *
- * @param value the value to set
- * @throws IOException if an error occurred during writing
- */
- public abstract void SetDTR(bool value);
-
- /**
- * Gets the RI (Ring Indicator) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetRI();
-
- /**
- * Gets the RTS (Request To Send) bit from the underlying UART.
- *
- * @return the current state, or {@code false} if not supported.
- * @throws IOException if an error occurred during reading
- */
- public abstract bool GetRTS();
-
- /**
- * Sets the RTS (Request To Send) bit on the underlying UART, if
- * supported.
- *
- * @param value the value to set
- * @throws IOException if an error occurred during writing
- */
- public abstract void SetRTS(bool value);
-
- /**
- * Flush non-transmitted output data and / or non-read input data
- * @param flushRX {@code true} to flush non-transmitted output data
- * @param flushTX {@code true} to flush non-read input data
- * @return {@code true} if the operation was successful, or
- * {@code false} if the operation is not supported by the driver or device
- * @throws IOException if an error occurred during flush
- */
- public abstract bool PurgeHwBuffers(bool flushRX, bool flushTX);
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialProber.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialProber.cs
deleted file mode 100644
index 44c8e6d..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialProber.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using System.Collections.Generic;
-using Android.Hardware.Usb;
-using Java.Lang;
-using Java.Lang.Reflect;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class UsbSerialProber
- {
- private ProbeTable mProbeTable;
-
- public UsbSerialProber(ProbeTable probeTable)
- {
- mProbeTable = probeTable;
- }
-
- public static UsbSerialProber GetDefaultProber()
- {
- return new UsbSerialProber(GetDefaultProbeTable());
- }
-
- public static ProbeTable DefaultProbeTable => GetDefaultProbeTable();
-
- public static ProbeTable GetDefaultProbeTable()
- {
- ProbeTable probeTable = new ProbeTable();
- probeTable.AddDriver(typeof(CdcAcmSerialDriver));
- probeTable.AddDriver(typeof(Cp21xxSerialDriver));
- probeTable.AddDriver(typeof(FtdiSerialDriver));
- probeTable.AddDriver(typeof(ProlificSerialDriver));
- probeTable.AddDriver(typeof(Ch34xSerialDriver));
- return probeTable;
- }
-
- /**
- * Finds and builds all possible {@link UsbSerialDriver UsbSerialDrivers}
- * from the currently-attached {@link UsbDevice} hierarchy. This method does
- * not require permission from the Android USB system, since it does not
- * open any of the devices.
- *
- * @param usbManager
- * @return a list, possibly empty, of all compatible drivers
- */
- public List FindAllDrivers(UsbManager usbManager)
- {
- List< IUsbSerialDriver > result = new List();
-
- foreach (UsbDevice usbDevice in usbManager.DeviceList.Values)
- {
- IUsbSerialDriver driver = ProbeDevice(usbDevice);
- if (driver != null)
- {
- result.Add(driver);
- }
- }
- return result;
- }
-
- /**
- * Probes a single device for a compatible driver.
- *
- * @param usbDevice the usb device to probe
- * @return a new {@link UsbSerialDriver} compatible with this device, or
- * {@code null} if none available.
- */
- public IUsbSerialDriver ProbeDevice(UsbDevice usbDevice)
- {
- int vendorId = usbDevice.VendorId;
- int productId = usbDevice.ProductId;
-
- var driverClass = mProbeTable.FindDriver(vendorId, productId);
- if (driverClass != null)
- {
- IUsbSerialDriver driver;
- try
- {
- driver = (IUsbSerialDriver)Activator.CreateInstance(driverClass, new System.Object[] {usbDevice});
- } catch (NoSuchMethodException e) {
- throw new RuntimeException(e);
- } catch (IllegalArgumentException e) {
- throw new RuntimeException(e);
- } catch (InstantiationException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- } catch (InvocationTargetException e) {
- throw new RuntimeException(e);
- }
- return driver;
- }
- return null;
- }
-
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialRuntimeException.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialRuntimeException.cs
deleted file mode 100644
index 0c8782f..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSerialRuntimeException.cs
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-using System;
-using Android.Runtime;
-using Java.Lang;
-
-namespace Hoho.Android.UsbSerial.driver
-{
- public class UsbSerialRuntimeException : RuntimeException
- {
- public UsbSerialRuntimeException() : base()
- {
- }
-
- public UsbSerialRuntimeException(Throwable throwable) : base(throwable)
- {
- }
-
- public UsbSerialRuntimeException(string detailMessage) : base(detailMessage)
- {
- }
-
- public UsbSerialRuntimeException(string detailMessage, Throwable throwable) : base(detailMessage, throwable)
- {
- }
-
- protected UsbSerialRuntimeException(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
- {
- }
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSupport.cs b/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSupport.cs
deleted file mode 100644
index c79f2fb..0000000
--- a/src/UI/UsbSerialForAndroid/UsbSerialForAndroid/driver/UsbSupport.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* Copyright 2017 Tyler Technologies Inc.
- *
- * Project home page: https://github.com/anotherlab/xamarin-usb-serial-for-android
- * Portions of this library are based on usb-serial-for-android (https://github.com/mik3y/usb-serial-for-android).
- * Portions of this library are based on Xamarin USB Serial for Android (https://bitbucket.org/lusovu/xamarinusbserial).
- */
-
-namespace Hoho.Android.UsbSerial.driver
-{
- ///
- /// Fixes Xamarin bug with missing constants
- /// https://forums.xamarin.com/discussion/comment/197948/#Comment_197948
- /// Filed as https://bugzilla.xamarin.com/show_bug.cgi?id=47663
- ///
- public class UsbSupport : Java.Lang.Object
- {
- public const int UsbClassAppSpec = 254;
- public const int UsbClassAudio = 1;
- public const int UsbClassCdcData = 10;
- public const int UsbClassComm = 2;
- public const int UsbClassContentSec = 13;
- public const int UsbClassCscid = 11;
- public const int UsbClassHid = 3;
- public const int UsbClassHub = 9;
- public const int UsbClassMassStorage = 8;
- public const int UsbClassMisc = 239;
- public const int UsbClassPerInterface = 0;
- public const int UsbClassPhysica = 5;
- public const int UsbClassPrinter = 7;
- public const int UsbClassStillImage = 6;
- public const int UsbClassVendorSpec = 255;
- public const int UsbClassVideo = 14;
- public const int UsbClassWirelessController = 234;
- public const int UsbDirOut = 0;
- public const int UsbDirIn = 128;
- public const int UsbEndpointDirMask = 128;
- public const int UsbEndpointNumberMask = 15;
- public const int UsbEndpointXferBulk = 2;
- public const int UsbEndpointXferControl = 0;
- public const int UsbEndpointXferInt = 3;
- public const int UsbEndpointXferIsoc = 1;
- }
-}
\ No newline at end of file
diff --git a/src/UI/UsbSerialForAndroid/azure-pipelines.yml b/src/UI/UsbSerialForAndroid/azure-pipelines.yml
deleted file mode 100644
index ac58c25..0000000
--- a/src/UI/UsbSerialForAndroid/azure-pipelines.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-# Xamarin.Android
-# Build a Xamarin.Android project.
-# Add steps that test, sign, and distribute an app, save build artifacts, and more:
-# https://docs.microsoft.com/azure/devops/pipelines/languages/xamarin
-
-trigger:
-- master
-
-pool:
- vmImage: 'macos-latest'
-
-variables:
- buildConfiguration: 'Release'
- outputDirectory: '$(build.binariesDirectory)/$(buildConfiguration)'
-
-steps:
-- task: NuGetToolInstaller@0
-
-- task: NuGetCommand@2
- inputs:
- restoreSolution: '**/*.sln'
-
-- task: XamarinAndroid@1
- inputs:
- projectFile: '**/*droid*.csproj'
- outputDirectory: '$(outputDirectory)'
- configuration: '$(buildConfiguration)'
diff --git a/src/UI/Windows/App.xaml b/src/UI/Windows/App.xaml
index 68df2ac..904c180 100644
--- a/src/UI/Windows/App.xaml
+++ b/src/UI/Windows/App.xaml
@@ -13,6 +13,7 @@
+
diff --git a/src/UI/Windows/App.xaml.cs b/src/UI/Windows/App.xaml.cs
index 124a9e2..37d36be 100644
--- a/src/UI/Windows/App.xaml.cs
+++ b/src/UI/Windows/App.xaml.cs
@@ -55,8 +55,9 @@ public partial class App
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
- services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
+ services.AddSingleton();
}).Build();
///
@@ -100,6 +101,23 @@ private async void OnStartup(object sender, StartupEventArgs e)
Host.Services.GetService();
Host.Services.GetService();
+
+ // Check for language mismatch after UI is initialized
+ _ = Task.Run(async () =>
+ {
+ // Small delay to ensure UI is fully loaded
+ await Task.Delay(500);
+
+ // Run on UI thread to ensure proper dialog display and culture updates
+ await Current.Dispatcher.InvokeAsync(async () =>
+ {
+ var languageMismatchService = Host.Services.GetService();
+ if (languageMismatchService != null)
+ {
+ await languageMismatchService.CheckAndPromptForLanguageMismatchAsync();
+ }
+ });
+ });
}
///
diff --git a/src/UI/Windows/Helpers/CopyTextBoxHelper.cs b/src/UI/Windows/Helpers/CopyTextBoxHelper.cs
index 79920ee..6b0479f 100644
--- a/src/UI/Windows/Helpers/CopyTextBoxHelper.cs
+++ b/src/UI/Windows/Helpers/CopyTextBoxHelper.cs
@@ -1,4 +1,3 @@
-using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
@@ -42,30 +41,24 @@ public static void SetCopyCommand(DependencyObject obj, ICommand value)
});
}
-public class RelayCommand : ICommand
+public class RelayCommand(Action execute, Func? canExecute = null)
+ : ICommand
{
- private readonly Action _execute;
- private readonly Func _canExecute;
+ private readonly Action _execute = execute ?? throw new ArgumentNullException(nameof(execute));
- public RelayCommand(Action execute, Func canExecute = null)
+ public event EventHandler? CanExecuteChanged
{
- _execute = execute ?? throw new ArgumentNullException(nameof(execute));
- _canExecute = canExecute;
+ add => CommandManager.RequerySuggested += value;
+ remove => CommandManager.RequerySuggested -= value;
}
- public event EventHandler CanExecuteChanged
+ public bool CanExecute(object? parameter)
{
- add { CommandManager.RequerySuggested += value; }
- remove { CommandManager.RequerySuggested -= value; }
+ return parameter != null && (canExecute?.Invoke(parameter) ?? true);
}
- public bool CanExecute(object parameter)
+ public void Execute(object? parameter)
{
- return _canExecute?.Invoke(parameter) ?? true;
- }
-
- public void Execute(object parameter)
- {
- _execute(parameter);
+ if (parameter != null) _execute(parameter);
}
}
\ No newline at end of file
diff --git a/src/UI/Windows/Markup/LocalizeExtension.cs b/src/UI/Windows/Markup/LocalizeExtension.cs
index 4270f54..84c3227 100644
--- a/src/UI/Windows/Markup/LocalizeExtension.cs
+++ b/src/UI/Windows/Markup/LocalizeExtension.cs
@@ -1,4 +1,3 @@
-using System.Globalization;
using System.Windows.Markup;
using System.Windows.Data;
using OSDPBench.Core.Resources;
diff --git a/src/UI/Windows/Markup/LocalizedStringBinding.cs b/src/UI/Windows/Markup/LocalizedStringBinding.cs
index 97cba19..59074f4 100644
--- a/src/UI/Windows/Markup/LocalizedStringBinding.cs
+++ b/src/UI/Windows/Markup/LocalizedStringBinding.cs
@@ -1,6 +1,4 @@
using System.ComponentModel;
-using System.Windows;
-using System.Windows.Data;
namespace OSDPBench.Windows.Markup;
@@ -16,10 +14,10 @@ public LocalizedStringBinding(string key)
_key = key;
// Subscribe to culture changes
- OSDPBench.Core.Resources.Resources.PropertyChanged += OnResourcesPropertyChanged;
+ Core.Resources.Resources.PropertyChanged += OnResourcesPropertyChanged;
}
- public string Value => OSDPBench.Core.Resources.Resources.GetString(_key);
+ public string Value => Core.Resources.Resources.GetString(_key);
private void OnResourcesPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
@@ -31,6 +29,6 @@ private void OnResourcesPropertyChanged(object? sender, PropertyChangedEventArgs
~LocalizedStringBinding()
{
- OSDPBench.Core.Resources.Resources.PropertyChanged -= OnResourcesPropertyChanged;
+ Core.Resources.Resources.PropertyChanged -= OnResourcesPropertyChanged;
}
}
\ No newline at end of file
diff --git a/src/UI/Windows/Services/WindowsDialogService.cs b/src/UI/Windows/Services/WindowsDialogService.cs
index b6418d8..3e7fe9b 100644
--- a/src/UI/Windows/Services/WindowsDialogService.cs
+++ b/src/UI/Windows/Services/WindowsDialogService.cs
@@ -45,8 +45,6 @@ public Task ShowExceptionDialog(string title, Exception exception)
private static string FormatExceptionMessage(Exception exception)
{
- if (exception == null) return "Unknown error occurred.";
-
return $"{exception.Message}\n\nDetails: {exception.GetType().Name}";
}
}
\ No newline at end of file
diff --git a/src/UI/Windows/Services/WindowsLanguageMismatchService.cs b/src/UI/Windows/Services/WindowsLanguageMismatchService.cs
new file mode 100644
index 0000000..7bbd450
--- /dev/null
+++ b/src/UI/Windows/Services/WindowsLanguageMismatchService.cs
@@ -0,0 +1,141 @@
+using System.Globalization;
+using System.Windows;
+using OSDPBench.Core.Services;
+using OSDPBench.Core.ViewModels.Dialogs;
+using OSDPBench.Windows.Views.Dialogs;
+
+namespace OSDPBench.Windows.Services;
+
+///
+/// Windows-specific implementation of the language mismatch service with custom dialog support
+///
+public class WindowsLanguageMismatchService : ILanguageMismatchService
+{
+ private readonly ILocalizationService _localizationService;
+ private readonly IUserSettingsService _userSettingsService;
+
+ ///
+ /// Initializes a new instance of the WindowsLanguageMismatchService
+ ///
+ /// The localization service
+ /// The user settings service
+ public WindowsLanguageMismatchService(
+ ILocalizationService localizationService,
+ IUserSettingsService userSettingsService)
+ {
+ _localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
+ _userSettingsService = userSettingsService ?? throw new ArgumentNullException(nameof(userSettingsService));
+ }
+
+ ///
+ public async Task CheckAndPromptForLanguageMismatchAsync()
+ {
+ System.Diagnostics.Debug.WriteLine("LanguageMismatchService: Starting check...");
+
+ // Only check if this is not the user's first time setting a language
+ if (string.IsNullOrEmpty(_userSettingsService.Settings.PreferredCulture))
+ {
+ System.Diagnostics.Debug.WriteLine("LanguageMismatchService: First time user - skipping");
+ return;
+ }
+
+ // Check if the user has disabled language mismatch checking
+ if (_userSettingsService.Settings.SkipLanguageMismatchCheck)
+ {
+ return;
+ }
+
+ // Check if there's a mismatch
+ var systemCulture = _localizationService.GetSystemCulture();
+ var isMatch = _localizationService.IsSystemLanguageMatch();
+
+ if (isMatch)
+ {
+ return;
+ }
+
+ var systemLanguageName = systemCulture.NativeName;
+
+ // Show custom dialog
+ var (userWantsToSwitch, dontAskAgain) = await ShowLanguageMismatchDialogAsync(systemLanguageName);
+
+ // Save the "don't ask again" preference
+ if (dontAskAgain)
+ {
+ await _userSettingsService.UpdateSettingsAsync(settings =>
+ settings.SkipLanguageMismatchCheck = true);
+ }
+
+ if (userWantsToSwitch)
+ {
+ // Find the best supported culture that matches the system language
+ var supportedCulture = FindBestMatchingCulture(systemCulture);
+ if (supportedCulture != null)
+ {
+ _localizationService.ChangeCulture(supportedCulture);
+ }
+ }
+ }
+
+ ///
+ public async Task<(bool userWantsToSwitch, bool dontAskAgain)> ShowLanguageMismatchDialogAsync(string systemLanguageName)
+ {
+ var tcs = new TaskCompletionSource<(bool, bool)>();
+
+ await Application.Current.Dispatcher.InvokeAsync(() =>
+ {
+ // Create the dialog content
+ var message = _localizationService.GetString("Language_SystemMismatchMessage", systemLanguageName);
+
+ Window? dialogWindow = null;
+ var window = dialogWindow;
+ var viewModel = new LanguageMismatchDialogViewModel(message, (userChoice, dontAsk) =>
+ {
+ tcs.SetResult((userChoice, dontAsk));
+ window?.Close();
+ });
+
+ var dialogContent = new LanguageMismatchDialog
+ {
+ DataContext = viewModel
+ };
+
+ // Create and show the dialog window
+ dialogWindow = new Window
+ {
+ Title = _localizationService.GetString("Language_SystemMismatchTitle"),
+ Content = dialogContent,
+ SizeToContent = SizeToContent.WidthAndHeight,
+ ResizeMode = ResizeMode.NoResize,
+ WindowStartupLocation = WindowStartupLocation.CenterOwner,
+ Owner = Application.Current.MainWindow,
+ ShowInTaskbar = false
+ };
+
+ dialogWindow.ShowDialog();
+ });
+
+ return await tcs.Task;
+ }
+
+ ///
+ /// Finds the best matching supported culture for the given system culture
+ ///
+ /// The system culture to match
+ /// The best matching supported culture, or null if none found
+ private CultureInfo? FindBestMatchingCulture(CultureInfo systemCulture)
+ {
+ var supportedCultures = _localizationService.SupportedCultures;
+
+ // First try the exact match
+ var exactMatch = supportedCultures.FirstOrDefault(c => c.Name == systemCulture.Name);
+ if (exactMatch != null)
+ return exactMatch;
+
+ // Then try base language match
+ var baseLanguageMatch = supportedCultures.FirstOrDefault(c =>
+ c.TwoLetterISOLanguageName == systemCulture.TwoLetterISOLanguageName);
+
+ return baseLanguageMatch;
+ }
+}
\ No newline at end of file
diff --git a/src/UI/Windows/Services/WindowsUsbDeviceMonitorService.cs b/src/UI/Windows/Services/WindowsUsbDeviceMonitorService.cs
index 76e4dfc..5d9d2e4 100644
--- a/src/UI/Windows/Services/WindowsUsbDeviceMonitorService.cs
+++ b/src/UI/Windows/Services/WindowsUsbDeviceMonitorService.cs
@@ -1,24 +1,19 @@
-using System;
-using System.Collections.Generic;
using System.IO.Ports;
-using System.Linq;
using System.Management;
-using System.Threading;
-using System.Threading.Tasks;
using OSDPBench.Core.Services;
namespace OSDPBench.Windows.Services;
///
-/// Windows implementation of USB device monitoring service using WMI events and polling.
+/// Windows implementation of the USB device monitoring service using WMI events and polling.
///
-public class WindowsUsbDeviceMonitorService : IUsbDeviceMonitorService
+public sealed class WindowsUsbDeviceMonitorService : IUsbDeviceMonitorService
{
private readonly SynchronizationContext? _synchronizationContext;
private ManagementEventWatcher? _deviceInsertWatcher;
private ManagementEventWatcher? _deviceRemoveWatcher;
private Timer? _pollingTimer;
- private HashSet _previousPorts = new();
+ private HashSet _previousPorts;
private bool _isDisposed;
private readonly object _lock = new();
@@ -54,15 +49,9 @@ public void StartMonitoring()
IsMonitoring = true;
}
- catch (Exception ex)
+ catch (Exception)
{
- // If WMI fails, continue with polling only
- Console.WriteLine($"WMI monitoring failed to start: {ex.Message}. Falling back to polling only.");
-
- if (_pollingTimer == null)
- {
- _pollingTimer = new Timer(OnPollingTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromSeconds(2));
- }
+ _pollingTimer ??= new Timer(OnPollingTimerElapsed, null, TimeSpan.Zero, TimeSpan.FromSeconds(2));
IsMonitoring = true;
}
@@ -84,54 +73,39 @@ public void StopMonitoring()
IsMonitoring = false;
}
}
-
+
private void StartWmiMonitoring()
{
- try
- {
- // Query for USB serial port device insertion
- var insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 " +
- "WHERE TargetInstance ISA 'Win32_PnPEntity' " +
- "AND (TargetInstance.PNPClass = 'Ports' OR TargetInstance.PNPClass = 'USB')");
-
- _deviceInsertWatcher = new ManagementEventWatcher(insertQuery);
- _deviceInsertWatcher.EventArrived += OnDeviceInserted;
- _deviceInsertWatcher.Start();
-
- // Query for USB serial port device removal
- var removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 " +
- "WHERE TargetInstance ISA 'Win32_PnPEntity' " +
- "AND (TargetInstance.PNPClass = 'Ports' OR TargetInstance.PNPClass = 'USB')");
-
- _deviceRemoveWatcher = new ManagementEventWatcher(removeQuery);
- _deviceRemoveWatcher.EventArrived += OnDeviceRemoved;
- _deviceRemoveWatcher.Start();
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Failed to start WMI monitoring: {ex.Message}");
- throw;
- }
+ // Query for USB serial port device insertion
+ var insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 " +
+ "WHERE TargetInstance ISA 'Win32_PnPEntity' " +
+ "AND (TargetInstance.PNPClass = 'Ports' OR TargetInstance.PNPClass = 'USB')");
+
+ _deviceInsertWatcher = new ManagementEventWatcher(insertQuery);
+ _deviceInsertWatcher.EventArrived += OnDeviceInserted;
+ _deviceInsertWatcher.Start();
+
+ // Query for USB serial port device removal
+ var removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 " +
+ "WHERE TargetInstance ISA 'Win32_PnPEntity' " +
+ "AND (TargetInstance.PNPClass = 'Ports' OR TargetInstance.PNPClass = 'USB')");
+
+ _deviceRemoveWatcher = new ManagementEventWatcher(removeQuery);
+ _deviceRemoveWatcher.EventArrived += OnDeviceRemoved;
+ _deviceRemoveWatcher.Start();
}
-
+
private void StopWmiMonitoring()
{
- try
- {
- _deviceInsertWatcher?.Stop();
- _deviceInsertWatcher?.Dispose();
- _deviceInsertWatcher = null;
-
- _deviceRemoveWatcher?.Stop();
- _deviceRemoveWatcher?.Dispose();
- _deviceRemoveWatcher = null;
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error stopping WMI monitoring: {ex.Message}");
- }
+ _deviceInsertWatcher?.Stop();
+ _deviceInsertWatcher?.Dispose();
+ _deviceInsertWatcher = null;
+
+ _deviceRemoveWatcher?.Stop();
+ _deviceRemoveWatcher?.Dispose();
+ _deviceRemoveWatcher = null;
}
-
+
private void OnDeviceInserted(object sender, EventArrivedEventArgs e)
{
Task.Run(() => CheckForPortChanges(UsbDeviceChangeType.Connected));
@@ -146,53 +120,45 @@ private void OnPollingTimerElapsed(object? state)
{
CheckForPortChanges(UsbDeviceChangeType.Unknown);
}
-
+
private void CheckForPortChanges(UsbDeviceChangeType suggestedChangeType)
{
- try
+ var currentPorts = new HashSet(SerialPort.GetPortNames());
+
+ lock (_lock)
{
- var currentPorts = new HashSet(SerialPort.GetPortNames());
-
- lock (_lock)
+ // Check if there are any changes
+ var addedPorts = currentPorts.Except(_previousPorts).ToArray();
+ var removedPorts = _previousPorts.Except(currentPorts).ToArray();
+
+ if (addedPorts.Any() && removedPorts.Any()) return;
+
+ // Determine the actual change type
+ UsbDeviceChangeType actualChangeType;
+ if (addedPorts.Any() && !removedPorts.Any())
{
- // Check if there are any changes
- var addedPorts = currentPorts.Except(_previousPorts).ToList();
- var removedPorts = _previousPorts.Except(currentPorts).ToList();
-
- if (addedPorts.Any() || removedPorts.Any())
- {
- // Determine the actual change type
- UsbDeviceChangeType actualChangeType;
- if (addedPorts.Any() && !removedPorts.Any())
- {
- actualChangeType = UsbDeviceChangeType.Connected;
- }
- else if (removedPorts.Any() && !addedPorts.Any())
- {
- actualChangeType = UsbDeviceChangeType.Disconnected;
- }
- else
- {
- // Both added and removed - use suggested or Unknown
- actualChangeType = suggestedChangeType != UsbDeviceChangeType.Unknown
- ? suggestedChangeType
- : UsbDeviceChangeType.Unknown;
- }
-
- _previousPorts = currentPorts;
-
- // Raise event on the UI thread if possible
- var eventArgs = new UsbDeviceChangedEventArgs(actualChangeType, currentPorts.ToList());
- RaiseUsbDeviceChanged(eventArgs);
- }
+ actualChangeType = UsbDeviceChangeType.Connected;
}
- }
- catch (Exception ex)
- {
- Console.WriteLine($"Error checking for port changes: {ex.Message}");
+ else if (removedPorts.Any() && !addedPorts.Any())
+ {
+ actualChangeType = UsbDeviceChangeType.Disconnected;
+ }
+ else
+ {
+ // Both added and removed - use suggested or Unknown
+ actualChangeType = suggestedChangeType != UsbDeviceChangeType.Unknown
+ ? suggestedChangeType
+ : UsbDeviceChangeType.Unknown;
+ }
+
+ _previousPorts = currentPorts;
+
+ // Raise event on the UI thread if possible
+ var eventArgs = new UsbDeviceChangedEventArgs(actualChangeType, currentPorts.ToList());
+ RaiseUsbDeviceChanged(eventArgs);
}
}
-
+
private void RaiseUsbDeviceChanged(UsbDeviceChangedEventArgs e)
{
if (_synchronizationContext != null)
@@ -209,13 +175,12 @@ private void RaiseUsbDeviceChanged(UsbDeviceChangedEventArgs e)
public void Dispose()
{
Dispose(true);
- GC.SuppressFinalize(this);
}
///
/// Releases unmanaged and - optionally - managed resources.
///
- protected virtual void Dispose(bool disposing)
+ private void Dispose(bool disposing)
{
if (_isDisposed) return;
diff --git a/src/Core/Services/UserSettingsService.cs b/src/UI/Windows/Services/WindowsUserSettingsService.cs
similarity index 86%
rename from src/Core/Services/UserSettingsService.cs
rename to src/UI/Windows/Services/WindowsUserSettingsService.cs
index 874e5dd..a48a8cc 100644
--- a/src/Core/Services/UserSettingsService.cs
+++ b/src/UI/Windows/Services/WindowsUserSettingsService.cs
@@ -1,20 +1,22 @@
+using System.IO;
using System.Text.Json;
using OSDPBench.Core.Models;
+using OSDPBench.Core.Services;
-namespace OSDPBench.Core.Services;
+namespace OSDPBench.Windows.Services;
///
-/// Implementation of user settings service using JSON file storage
+/// Windows implementation of a user settings service using JSON file storage
///
-public class UserSettingsService : IUserSettingsService
+public class WindowsUserSettingsService : IUserSettingsService
{
private readonly string _settingsFilePath;
private UserSettings _settings;
///
- /// Initializes a new instance of the UserSettingsService
+ /// Initializes a new instance of the WindowsUserSettingsService
///
- public UserSettingsService()
+ public WindowsUserSettingsService()
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appFolderPath = Path.Combine(appDataPath, "OSDPBench");
diff --git a/src/UI/Windows/Styles/ComponentStyles.xaml b/src/UI/Windows/Styles/ComponentStyles.xaml
index 811d27a..f24c5e9 100644
--- a/src/UI/Windows/Styles/ComponentStyles.xaml
+++ b/src/UI/Windows/Styles/ComponentStyles.xaml
@@ -49,15 +49,19 @@
+
+
@@ -112,17 +116,17 @@
-
+
-
@@ -165,6 +169,7 @@
+
+
diff --git a/src/UI/Windows/Styles/DesignTokens.xaml b/src/UI/Windows/Styles/DesignTokens.xaml
index 9cf8fb9..8c2be05 100644
--- a/src/UI/Windows/Styles/DesignTokens.xaml
+++ b/src/UI/Windows/Styles/DesignTokens.xaml
@@ -1,6 +1,5 @@
@@ -38,12 +37,17 @@
32
36
-
+
+
+
+
+
+
diff --git a/src/UI/Windows/Styles/LayoutTemplates.xaml b/src/UI/Windows/Styles/LayoutTemplates.xaml
index 6593e8a..cfcfcd1 100644
--- a/src/UI/Windows/Styles/LayoutTemplates.xaml
+++ b/src/UI/Windows/Styles/LayoutTemplates.xaml
@@ -2,41 +2,87 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:controls="clr-namespace:OSDPBench.Windows.Views.Controls"
- xmlns:markup="clr-namespace:OSDPBench.Windows.Markup">
+ xmlns:markup="clr-namespace:OSDPBench.Windows.Markup"
+ xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -55,21 +101,21 @@
TextAlignment="Center"
TextWrapping="Wrap"
HorizontalAlignment="Center"
- Margin="16,0">
+ Margin="16,0" d:DataContext="{d:DesignInstance }">
diff --git a/src/UI/Windows/Styles/ThemeSemanticColors.xaml b/src/UI/Windows/Styles/ThemeSemanticColors.xaml
new file mode 100644
index 0000000..196a4ee
--- /dev/null
+++ b/src/UI/Windows/Styles/ThemeSemanticColors.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/UI/Windows/Views/Controls/FileTransferControl.xaml.cs b/src/UI/Windows/Views/Controls/FileTransferControl.xaml.cs
index 49324f4..885c506 100644
--- a/src/UI/Windows/Views/Controls/FileTransferControl.xaml.cs
+++ b/src/UI/Windows/Views/Controls/FileTransferControl.xaml.cs
@@ -1,5 +1,4 @@
using System.Windows;
-using System.Windows.Controls;
using Microsoft.Win32;
using OSDPBench.Core.Models;
diff --git a/src/UI/Windows/Views/Controls/LedControl.xaml b/src/UI/Windows/Views/Controls/LedControl.xaml
index 3295eca..28be798 100644
--- a/src/UI/Windows/Views/Controls/LedControl.xaml
+++ b/src/UI/Windows/Views/Controls/LedControl.xaml
@@ -9,9 +9,9 @@
+ Fill="{DynamicResource SemanticErrorBrush}">
-
+
diff --git a/src/UI/Windows/Views/Controls/SetReaderLedControl.xaml b/src/UI/Windows/Views/Controls/SetReaderLedControl.xaml
index 9d78cda..4995da6 100644
--- a/src/UI/Windows/Views/Controls/SetReaderLedControl.xaml
+++ b/src/UI/Windows/Views/Controls/SetReaderLedControl.xaml
@@ -3,7 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
xmlns:controls="clr-namespace:OSDPBench.Windows.Views.Controls"
xmlns:markup="clr-namespace:OSDPBench.Windows.Markup"
mc:Ignorable="d"
diff --git a/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml b/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml
new file mode 100644
index 0000000..a0abbcf
--- /dev/null
+++ b/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml
@@ -0,0 +1,55 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml.cs b/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml.cs
new file mode 100644
index 0000000..5fefac9
--- /dev/null
+++ b/src/UI/Windows/Views/Dialogs/LanguageMismatchDialog.xaml.cs
@@ -0,0 +1,12 @@
+namespace OSDPBench.Windows.Views.Dialogs;
+
+///
+/// Interaction logic for LanguageMismatchDialog.xaml
+///
+public partial class LanguageMismatchDialog
+{
+ public LanguageMismatchDialog()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/src/UI/Windows/Views/Pages/ConnectPage.xaml b/src/UI/Windows/Views/Pages/ConnectPage.xaml
index 4ea914c..226814b 100644
--- a/src/UI/Windows/Views/Pages/ConnectPage.xaml
+++ b/src/UI/Windows/Views/Pages/ConnectPage.xaml
@@ -25,7 +25,7 @@
Template="{StaticResource Template.PageHeader}"/>
-
@@ -60,39 +60,32 @@
-
+
-
-
+
+
+
-
-
+
+
-
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+ VerticalAlignment="Center"
+ HorizontalAlignment="Right"
+ Margin="0,0,0,10">
-
+
@@ -140,11 +133,8 @@
-
+
@@ -180,11 +170,8 @@
Padding="16"
Margin="0,0,0,16">
-
+
();
+ UpdateConnectionTypes();
+
// Subscribe to culture changes
Core.Resources.Resources.PropertyChanged += OnResourcesPropertyChanged;
@@ -26,16 +30,25 @@ public ConnectPage(ConnectViewModel viewModel)
InitializeComponent();
// Set up loaded event to ensure proper initialization
- this.Loaded += OnPageLoaded;
+ Loaded += OnPageLoaded;
}
public ConnectViewModel ViewModel { get; }
- public IEnumerable ConnectionTypes =>
- [
- Core.Resources.Resources.GetString("ConnectionType_Discover"),
- Core.Resources.Resources.GetString("ConnectionType_Manual")
- ];
+ private readonly System.Collections.ObjectModel.ObservableCollection _connectionTypes;
+ public System.Collections.ObjectModel.ObservableCollection ConnectionTypes => _connectionTypes;
+
+ private void UpdateConnectionTypes()
+ {
+ int previousSelectedConnectionTypeIndex = SelectedConnectionTypeIndex;
+
+ _connectionTypes.Clear();
+
+ _connectionTypes.Add(Core.Resources.Resources.GetString("ConnectionType_Discover"));
+ _connectionTypes.Add(Core.Resources.Resources.GetString("ConnectionType_Manual"));
+
+ SelectedConnectionTypeIndex = previousSelectedConnectionTypeIndex;
+ }
private int _selectedConnectionTypeIndex = -1; // Start with -1 to ensure property change fires
@@ -92,13 +105,12 @@ private Visibility CalculateCancelDiscoveryVisibility()
private void OnResourcesPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
- // When culture changes, notify that ConnectionTypes has changed
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(ConnectionTypes)));
-
- // Force the ComboBox to refresh its selection
- var currentIndex = SelectedConnectionTypeIndex;
- SelectedConnectionTypeIndex = -1;
- SelectedConnectionTypeIndex = currentIndex;
+ // When culture changes, update the connection types with new localized strings
+ // Since we're updating in place. The selection should be maintained
+ UpdateConnectionTypes();
+
+ // Ensure the UI updates properly
+ UpdateButtonVisibility();
}
private void OnViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
@@ -137,4 +149,31 @@ private void AddressNumberBox_OnValueChanged(object sender, NumberBoxValueChange
{
ViewModel.SelectedAddress = (byte)(AddressNumberBox.Value ?? 0);
}
+
+ private void OnConnectionGridSizeChanged(object sender, SizeChangedEventArgs e)
+ {
+ // Check if we have enough width for side-by-side layout
+ // Threshold of 500 pixels seems reasonable for this layout
+ const double widthThreshold = 500;
+
+ if (ButtonPanel != null)
+ {
+ if (e.NewSize.Width < widthThreshold)
+ {
+ // Narrow: Move buttons to the second row, left aligned
+ Grid.SetRow(ButtonPanel, 1);
+ Grid.SetColumn(ButtonPanel, 0);
+ Grid.SetColumnSpan(ButtonPanel, 2);
+ ButtonPanel.HorizontalAlignment = HorizontalAlignment.Left;
+ }
+ else
+ {
+ // Wide: Buttons on same row as title, right aligned
+ Grid.SetRow(ButtonPanel, 0);
+ Grid.SetColumn(ButtonPanel, 1);
+ Grid.SetColumnSpan(ButtonPanel, 1);
+ ButtonPanel.HorizontalAlignment = HorizontalAlignment.Right;
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/src/UI/Windows/Views/Pages/InfoPage.xaml b/src/UI/Windows/Views/Pages/InfoPage.xaml
index b083612..3569431 100644
--- a/src/UI/Windows/Views/Pages/InfoPage.xaml
+++ b/src/UI/Windows/Views/Pages/InfoPage.xaml
@@ -72,17 +72,17 @@
@@ -90,17 +90,17 @@
@@ -108,16 +108,16 @@
diff --git a/src/UI/Windows/Views/Pages/InvertEffect.cs b/src/UI/Windows/Views/Pages/InvertEffect.cs
index a5d3841..b879c90 100644
--- a/src/UI/Windows/Views/Pages/InvertEffect.cs
+++ b/src/UI/Windows/Views/Pages/InvertEffect.cs
@@ -28,6 +28,6 @@ public InvertEffect()
}
public static readonly DependencyProperty InputProperty =
- ShaderEffect.RegisterPixelShaderSamplerProperty("Input", typeof(InvertEffect), 0);
+ RegisterPixelShaderSamplerProperty("Input", typeof(InvertEffect), 0);
}
\ No newline at end of file
diff --git a/src/UI/Windows/Views/Pages/ManagePage.xaml b/src/UI/Windows/Views/Pages/ManagePage.xaml
index da2dadd..c515d07 100644
--- a/src/UI/Windows/Views/Pages/ManagePage.xaml
+++ b/src/UI/Windows/Views/Pages/ManagePage.xaml
@@ -18,34 +18,11 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
@@ -141,23 +118,12 @@
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
diff --git a/src/UI/Windows/Views/Pages/MonitorPage.xaml.cs b/src/UI/Windows/Views/Pages/MonitorPage.xaml.cs
index 8c00e35..72ac7f1 100644
--- a/src/UI/Windows/Views/Pages/MonitorPage.xaml.cs
+++ b/src/UI/Windows/Views/Pages/MonitorPage.xaml.cs
@@ -4,7 +4,6 @@
using OSDPBench.Core.ViewModels.Pages;
using Wpf.Ui.Abstractions.Controls;
using Button = Wpf.Ui.Controls.Button;
-using OSDPBench.Core.Resources;
using Wpf.Ui.Controls;
namespace OSDPBench.Windows.Views.Pages;
@@ -36,7 +35,7 @@ private void ToggleRowDetails(object sender, RoutedEventArgs e)
: Visibility.Visible;
button.Icon = new SymbolIcon { Symbol = row.DetailsVisibility == Visibility.Visible ? SymbolRegular.ChevronUp24 : SymbolRegular.ChevronDown24 };
- button.ToolTip = row.DetailsVisibility == Visibility.Visible ? OSDPBench.Core.Resources.Resources.GetString("Monitor_Collapse") : OSDPBench.Core.Resources.Resources.GetString("Monitor_Expand");
+ button.ToolTip = row.DetailsVisibility == Visibility.Visible ? Core.Resources.Resources.GetString("Monitor_Collapse") : Core.Resources.Resources.GetString("Monitor_Expand");
}
}
}
diff --git a/src/UI/Windows/Windows.csproj b/src/UI/Windows/Windows.csproj
index 02da521..27b1ff4 100644
--- a/src/UI/Windows/Windows.csproj
+++ b/src/UI/Windows/Windows.csproj
@@ -16,10 +16,10 @@
-
-
+
+
-
+
diff --git a/test/Core.Tests/Core.Tests.csproj b/test/Core.Tests/Core.Tests.csproj
index a6bbd74..bbeb3af 100644
--- a/test/Core.Tests/Core.Tests.csproj
+++ b/test/Core.Tests/Core.Tests.csproj
@@ -23,7 +23,7 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
diff --git a/test/Core.Tests/ViewModels/UsbMonitoringTests.cs b/test/Core.Tests/ViewModels/UsbMonitoringTests.cs
index 5068359..9282332 100644
--- a/test/Core.Tests/ViewModels/UsbMonitoringTests.cs
+++ b/test/Core.Tests/ViewModels/UsbMonitoringTests.cs
@@ -26,7 +26,7 @@ public void Setup()
public void ConnectViewModel_WithUsbMonitorService_StartsMonitoring()
{
// Act
- var viewModel = new ConnectViewModel(
+ using var viewModel = new ConnectViewModel(
_mockDialogService.Object,
_mockDeviceManagementService.Object,
_mockSerialPortConnectionService.Object,
@@ -40,11 +40,14 @@ public void ConnectViewModel_WithUsbMonitorService_StartsMonitoring()
public void ConnectViewModel_WithoutUsbMonitorService_DoesNotThrow()
{
// Act & Assert
- Assert.DoesNotThrow(() => new ConnectViewModel(
- _mockDialogService.Object,
- _mockDeviceManagementService.Object,
- _mockSerialPortConnectionService.Object,
- null));
+ // ReSharper disable once ObjectCreationAsStatement
+ Assert.DoesNotThrow(() =>
+ {
+ using var viewModel = new ConnectViewModel(
+ _mockDialogService.Object,
+ _mockDeviceManagementService.Object,
+ _mockSerialPortConnectionService.Object);
+ });
}
[Test]