├── .github └── workflows │ └── driver-cross-build.yml ├── .gitignore ├── .test ├── bin │ └── run-clang-format.py └── lint.sh ├── 50-rtmouse.rules ├── LICENSE ├── README.md ├── SampleProgram ├── .clang-format ├── LICENSE ├── README.md ├── RemoCon_Step1.sh ├── RemoCon_for_PS3.py ├── SCALE ├── step1.c ├── step1.py ├── step1.sh ├── step2.c ├── step2.py ├── step2.sh ├── step3.c ├── step3.py ├── step3.sh ├── step4.c ├── step4.py ├── step4.sh ├── step5.c ├── step5.py ├── step5.sh ├── step6.c ├── step6.py └── step6.sh ├── cad_data └── README.md ├── lib ├── Pi1B+ │ ├── 3.18.14+ │ │ └── rtmouse.ko │ ├── 4.0.5+ │ │ └── rtmouse.ko │ ├── 4.0.6+ │ │ └── rtmouse.ko │ ├── 4.0.7+ │ │ └── rtmouse.ko │ ├── 4.0.8+ │ │ └── rtmouse.ko │ ├── 4.0.9+ │ │ └── rtmouse.ko │ ├── 4.1.10+ │ │ └── rtmouse.ko │ ├── 4.1.13+ │ │ └── rtmouse.ko │ ├── 4.1.15+ │ │ └── rtmouse.ko │ ├── 4.1.5+ │ │ └── rtmouse.ko │ ├── 4.1.6+ │ │ └── rtmouse.ko │ ├── 4.1.7+ │ │ └── rtmouse.ko │ ├── 4.1.8+ │ │ └── rtmouse.ko │ └── 4.1.9+ │ │ └── rtmouse.ko └── Pi2B+ │ ├── 3.18.0-20-rpi2 │ └── rtmouse.ko │ ├── 3.18.9-v7+ │ └── rtmouse.ko │ ├── 4.0.5-v7+ │ └── rtmouse.ko │ ├── 4.0.6-v7+ │ └── rtmouse.ko │ ├── 4.0.7-v7+ │ └── rtmouse.ko │ ├── 4.0.8-v7+ │ └── rtmouse.ko │ ├── 4.0.9-v7+ │ └── rtmouse.ko │ ├── 4.1.10-v7+ │ └── rtmouse.ko │ ├── 4.1.13-v7+ │ └── rtmouse.ko │ ├── 4.1.15-v7+ │ └── rtmouse.ko │ ├── 4.1.17-v7+ │ └── rtmouse.ko │ ├── 4.1.19-v7+ │ └── rtmouse.ko │ ├── 4.1.21-v7+ │ └── rtmouse.ko │ ├── 4.1.5-v7+ │ └── rtmouse.ko │ ├── 4.1.6-v7+ │ └── rtmouse.ko │ ├── 4.1.7-v7+ │ └── rtmouse.ko │ ├── 4.1.8-v7+ │ └── rtmouse.ko │ ├── 4.1.9-v7+ │ └── rtmouse.ko │ ├── 4.14.50-v7+ │ └── rtmouse.ko │ ├── 4.14.69-v7+ │ └── rtmouse.ko │ ├── 4.14.70-v7+ │ └── rtmouse.ko │ ├── 4.14.98-v7+ │ └── rtmouse.ko │ ├── 4.19.42-v7+ │ └── rtmouse.ko │ ├── 4.19.75-v7+ │ └── rtmouse.ko │ ├── 4.19.97-v7+ │ └── rtmouse.ko │ ├── 4.4.0-1009-raspi2 │ └── rtmouse.ko │ ├── 4.4.10-v7+ │ └── rtmouse.ko │ ├── 4.4.13-v7+ │ └── rtmouse.ko │ ├── 4.4.14-v7+ │ └── rtmouse.ko │ ├── 4.4.21-v7+ │ └── rtmouse.ko │ ├── 4.4.34-v7+ │ └── rtmouse.ko │ ├── 4.4.35-v7+ │ └── rtmouse.ko │ ├── 4.4.39-v7+ │ └── rtmouse.ko │ ├── 4.4.41-v7+ │ └── rtmouse.ko │ ├── 4.4.50-v7+ │ └── rtmouse.ko │ ├── 4.4.9-v7+ │ └── rtmouse.ko │ ├── 4.9.35-v7+ │ └── rtmouse.ko │ ├── 4.9.51-v7+ │ └── rtmouse.ko │ ├── 4.9.70-v7+ │ └── rtmouse.ko │ └── 4.9.80-v7+ │ └── rtmouse.ko ├── src └── drivers │ ├── .clang-format │ ├── Makefile │ ├── Makefile.header_from_apt │ ├── Makefile.header_from_source │ ├── rtmouse.h │ ├── rtmouse_dev.c │ ├── rtmouse_gpio.c │ ├── rtmouse_i2c.c │ ├── rtmouse_main.c │ └── rtmouse_spi.c ├── supplement └── README.md └── utils ├── build_install.bash ├── build_install.raspbian.bash ├── build_install.ubuntu14.bash ├── build_install_header_from_apt_raspi2.bash ├── build_install_header_from_apt_raspi4.bash ├── build_install_header_from_source_raspi2.bash ├── build_install_header_from_source_raspi4.bash ├── print_env.bash └── set_configs.bash /.github/workflows/driver-cross-build.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | paths: 8 | - '.github/workflows/driver-cross-build.yml' 9 | - '.test/**' 10 | - 'src/drivers/**' 11 | workflow_dispatch: 12 | pull_request: 13 | types: [opened, synchronize] 14 | paths: 15 | - '.github/workflows/driver-cross-build.yml' 16 | - '.test/**' 17 | - 'src/drivers/**' 18 | 19 | jobs: 20 | lint: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: actions/setup-python@v5 26 | with: 27 | python-version: '3.x' 28 | 29 | - name: Lint 30 | run: | 31 | ./.test/lint.sh 32 | 33 | build: 34 | needs: lint 35 | strategy: 36 | fail-fast: false 37 | matrix: 38 | env: 39 | # Debian 10 (Buster) 40 | - { HOST: 20.04, KERNEL_VER: rpi-5.4.y, OS_BIT: armhf, RASPI: 3} 41 | - { HOST: 20.04, KERNEL_VER: rpi-5.4.y, OS_BIT: armhf, RASPI: 4} 42 | # Debian 11 (Bullseye) 43 | - { HOST: 20.04, KERNEL_VER: rpi-5.10.y, OS_BIT: armhf, RASPI: 3} 44 | - { HOST: 20.04, KERNEL_VER: rpi-5.10.y, OS_BIT: armhf, RASPI: 4} 45 | # Debian 11 (Bullseye) 46 | - { HOST: 22.04, KERNEL_VER: rpi-5.15.y, OS_BIT: armhf, RASPI: 3} 47 | - { HOST: 22.04, KERNEL_VER: rpi-5.15.y, OS_BIT: armhf, RASPI: 4} 48 | # Debian 12 (Bookworm) 32-bit 49 | - { HOST: 24.04, KERNEL_VER: rpi-6.6.y, OS_BIT: armhf, RASPI: 3} 50 | - { HOST: 24.04, KERNEL_VER: rpi-6.6.y, OS_BIT: armhf, RASPI: 4} 51 | # Debian 12 (Bookworm) 64-bit 52 | - { HOST: 24.04, KERNEL_VER: rpi-6.6.y, OS_BIT: arm64, RASPI: 3} 53 | - { HOST: 24.04, KERNEL_VER: rpi-6.6.y, OS_BIT: arm64, RASPI: 4} 54 | 55 | 56 | runs-on: ubuntu-${{ matrix.env.HOST }} 57 | 58 | steps: 59 | - name: Checkout source code 60 | uses: actions/checkout@v4 61 | 62 | - name: Set up cross-compilation toolchain 63 | run: | 64 | sudo apt update 65 | sudo apt install -y bc bison flex libssl-dev make libc6-dev libncurses5-dev 66 | if [ "${{ matrix.env.OS_BIT }}" == "armhf" ]; then 67 | sudo apt install -y crossbuild-essential-armhf 68 | else 69 | sudo apt install -y crossbuild-essential-arm64 70 | fi 71 | 72 | - name: Clone Raspberry Pi Linux Kernel 73 | run: | 74 | git clone --branch ${{ matrix.env.KERNEL_VER }} --depth=1 https://github.com/raspberrypi/linux 75 | cd linux 76 | if [ "${{ matrix.env.OS_BIT }}" == "armhf" ]; then 77 | if [ "${{ matrix.env.RASPI }}" == "3" ]; then 78 | KERNEL=kernel7 79 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig 80 | elif [ "${{ matrix.env.RASPI }}" == "4" ]; then 81 | KERNEL=kernel7l 82 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2711_defconfig 83 | fi 84 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules_prepare 85 | else 86 | KERNEL=kernel8 87 | make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcm2711_defconfig 88 | make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- modules_prepare 89 | fi 90 | 91 | - name: Build the kernel module 92 | run: | 93 | cd linux 94 | if [ "${{ matrix.env.OS_BIT }}" == "armhf" ]; then 95 | make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- M=$GITHUB_WORKSPACE/src/drivers V=1 KBUILD_MODPOST_WARN=1 modules 96 | else 97 | make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- M=$GITHUB_WORKSPACE/src/drivers V=1 KBUILD_MODPOST_WARN=1 modules 98 | fi 99 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/210c95bb02f629e5166c21e888b10d0c26442fe7/C.gitignore 2 | 3 | # Prerequisites 4 | *.d 5 | 6 | # Object files 7 | *.o 8 | *.ko 9 | *.obj 10 | *.elf 11 | 12 | # Linker output 13 | *.ilk 14 | *.map 15 | *.exp 16 | 17 | # Precompiled Headers 18 | *.gch 19 | *.pch 20 | 21 | # Libraries 22 | *.lib 23 | *.a 24 | *.la 25 | *.lo 26 | 27 | # Shared objects (inc. Windows DLLs) 28 | *.dll 29 | *.so 30 | *.so.* 31 | *.dylib 32 | 33 | # Executables 34 | *.exe 35 | *.out 36 | *.app 37 | *.i*86 38 | *.x86_64 39 | *.hex 40 | 41 | # Debug files 42 | *.dSYM/ 43 | *.su 44 | *.idb 45 | *.pdb 46 | 47 | # Kernel Module Compile Results 48 | *.mod* 49 | *.cmd 50 | .tmp_versions/ 51 | modules.order 52 | Module.symvers 53 | Mkfile.old 54 | dkms.conf 55 | -------------------------------------------------------------------------------- /.test/bin/run-clang-format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | """A wrapper script around clang-format, suitable for linting multiple files 4 | and to use for continuous integration. 5 | 6 | This is an alternative API for the clang-format command line. 7 | It runs over multiple files and directories in parallel. 8 | A diff output is produced and a sensible exit code is returned. 9 | 10 | # https://github.com/Sarcasm/run-clang-format/blob/39081c9c42768ab5e8321127a7494ad1647c6a2f/run-clang-format.py 11 | 12 | MIT License 13 | 14 | Copyright (c) 2017 Guillaume Papin 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | """ 34 | 35 | from __future__ import print_function, unicode_literals 36 | 37 | import argparse 38 | import codecs 39 | import difflib 40 | import fnmatch 41 | import io 42 | import errno 43 | import multiprocessing 44 | import os 45 | import signal 46 | import subprocess 47 | import sys 48 | import traceback 49 | 50 | from functools import partial 51 | 52 | try: 53 | from subprocess import DEVNULL # py3k 54 | except ImportError: 55 | DEVNULL = open(os.devnull, "wb") 56 | 57 | 58 | DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx' 59 | DEFAULT_CLANG_FORMAT_IGNORE = '.clang-format-ignore' 60 | 61 | 62 | class ExitStatus: 63 | SUCCESS = 0 64 | DIFF = 1 65 | TROUBLE = 2 66 | 67 | def excludes_from_file(ignore_file): 68 | excludes = [] 69 | try: 70 | with io.open(ignore_file, 'r', encoding='utf-8') as f: 71 | for line in f: 72 | if line.startswith('#'): 73 | # ignore comments 74 | continue 75 | pattern = line.rstrip() 76 | if not pattern: 77 | # allow empty lines 78 | continue 79 | excludes.append(pattern) 80 | except EnvironmentError as e: 81 | if e.errno != errno.ENOENT: 82 | raise 83 | return excludes; 84 | 85 | def list_files(files, recursive=False, extensions=None, exclude=None): 86 | if extensions is None: 87 | extensions = [] 88 | if exclude is None: 89 | exclude = [] 90 | 91 | out = [] 92 | for file in files: 93 | if recursive and os.path.isdir(file): 94 | for dirpath, dnames, fnames in os.walk(file): 95 | fpaths = [os.path.join(dirpath, fname) for fname in fnames] 96 | for pattern in exclude: 97 | # os.walk() supports trimming down the dnames list 98 | # by modifying it in-place, 99 | # to avoid unnecessary directory listings. 100 | dnames[:] = [ 101 | x for x in dnames 102 | if 103 | not fnmatch.fnmatch(os.path.join(dirpath, x), pattern) 104 | ] 105 | fpaths = [ 106 | x for x in fpaths if not fnmatch.fnmatch(x, pattern) 107 | ] 108 | for f in fpaths: 109 | ext = os.path.splitext(f)[1][1:] 110 | if ext in extensions: 111 | out.append(f) 112 | else: 113 | out.append(file) 114 | return out 115 | 116 | 117 | def make_diff(file, original, reformatted): 118 | return list( 119 | difflib.unified_diff( 120 | original, 121 | reformatted, 122 | fromfile='{}\t(original)'.format(file), 123 | tofile='{}\t(reformatted)'.format(file), 124 | n=3)) 125 | 126 | 127 | class DiffError(Exception): 128 | def __init__(self, message, errs=None): 129 | super(DiffError, self).__init__(message) 130 | self.errs = errs or [] 131 | 132 | 133 | class UnexpectedError(Exception): 134 | def __init__(self, message, exc=None): 135 | super(UnexpectedError, self).__init__(message) 136 | self.formatted_traceback = traceback.format_exc() 137 | self.exc = exc 138 | 139 | 140 | def run_clang_format_diff_wrapper(args, file): 141 | try: 142 | ret = run_clang_format_diff(args, file) 143 | return ret 144 | except DiffError: 145 | raise 146 | except Exception as e: 147 | raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__, 148 | e), e) 149 | 150 | 151 | def run_clang_format_diff(args, file): 152 | try: 153 | with io.open(file, 'r', encoding='utf-8') as f: 154 | original = f.readlines() 155 | except IOError as exc: 156 | raise DiffError(str(exc)) 157 | 158 | if args.in_place: 159 | invocation = [args.clang_format_executable, '-i', file] 160 | else: 161 | invocation = [args.clang_format_executable, file] 162 | 163 | if args.style: 164 | invocation.extend(['--style', args.style]) 165 | 166 | if args.dry_run: 167 | print(" ".join(invocation)) 168 | return [], [] 169 | 170 | # Use of utf-8 to decode the process output. 171 | # 172 | # Hopefully, this is the correct thing to do. 173 | # 174 | # It's done due to the following assumptions (which may be incorrect): 175 | # - clang-format will returns the bytes read from the files as-is, 176 | # without conversion, and it is already assumed that the files use utf-8. 177 | # - if the diagnostics were internationalized, they would use utf-8: 178 | # > Adding Translations to Clang 179 | # > 180 | # > Not possible yet! 181 | # > Diagnostic strings should be written in UTF-8, 182 | # > the client can translate to the relevant code page if needed. 183 | # > Each translation completely replaces the format string 184 | # > for the diagnostic. 185 | # > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation 186 | # 187 | # It's not pretty, due to Python 2 & 3 compatibility. 188 | encoding_py3 = {} 189 | if sys.version_info[0] >= 3: 190 | encoding_py3['encoding'] = 'utf-8' 191 | 192 | try: 193 | proc = subprocess.Popen( 194 | invocation, 195 | stdout=subprocess.PIPE, 196 | stderr=subprocess.PIPE, 197 | universal_newlines=True, 198 | **encoding_py3) 199 | except OSError as exc: 200 | raise DiffError( 201 | "Command '{}' failed to start: {}".format( 202 | subprocess.list2cmdline(invocation), exc 203 | ) 204 | ) 205 | proc_stdout = proc.stdout 206 | proc_stderr = proc.stderr 207 | if sys.version_info[0] < 3: 208 | # make the pipes compatible with Python 3, 209 | # reading lines should output unicode 210 | encoding = 'utf-8' 211 | proc_stdout = codecs.getreader(encoding)(proc_stdout) 212 | proc_stderr = codecs.getreader(encoding)(proc_stderr) 213 | # hopefully the stderr pipe won't get full and block the process 214 | outs = list(proc_stdout.readlines()) 215 | errs = list(proc_stderr.readlines()) 216 | proc.wait() 217 | if proc.returncode: 218 | raise DiffError( 219 | "Command '{}' returned non-zero exit status {}".format( 220 | subprocess.list2cmdline(invocation), proc.returncode 221 | ), 222 | errs, 223 | ) 224 | if args.in_place: 225 | return [], errs 226 | return make_diff(file, original, outs), errs 227 | 228 | 229 | def bold_red(s): 230 | return '\x1b[1m\x1b[31m' + s + '\x1b[0m' 231 | 232 | 233 | def colorize(diff_lines): 234 | def bold(s): 235 | return '\x1b[1m' + s + '\x1b[0m' 236 | 237 | def cyan(s): 238 | return '\x1b[36m' + s + '\x1b[0m' 239 | 240 | def green(s): 241 | return '\x1b[32m' + s + '\x1b[0m' 242 | 243 | def red(s): 244 | return '\x1b[31m' + s + '\x1b[0m' 245 | 246 | for line in diff_lines: 247 | if line[:4] in ['--- ', '+++ ']: 248 | yield bold(line) 249 | elif line.startswith('@@ '): 250 | yield cyan(line) 251 | elif line.startswith('+'): 252 | yield green(line) 253 | elif line.startswith('-'): 254 | yield red(line) 255 | else: 256 | yield line 257 | 258 | 259 | def print_diff(diff_lines, use_color): 260 | if use_color: 261 | diff_lines = colorize(diff_lines) 262 | if sys.version_info[0] < 3: 263 | sys.stdout.writelines((l.encode('utf-8') for l in diff_lines)) 264 | else: 265 | sys.stdout.writelines(diff_lines) 266 | 267 | 268 | def print_trouble(prog, message, use_colors): 269 | error_text = 'error:' 270 | if use_colors: 271 | error_text = bold_red(error_text) 272 | print("{}: {} {}".format(prog, error_text, message), file=sys.stderr) 273 | 274 | 275 | def main(): 276 | parser = argparse.ArgumentParser(description=__doc__) 277 | parser.add_argument( 278 | '--clang-format-executable', 279 | metavar='EXECUTABLE', 280 | help='path to the clang-format executable', 281 | default='clang-format') 282 | parser.add_argument( 283 | '--extensions', 284 | help='comma separated list of file extensions (default: {})'.format( 285 | DEFAULT_EXTENSIONS), 286 | default=DEFAULT_EXTENSIONS) 287 | parser.add_argument( 288 | '-r', 289 | '--recursive', 290 | action='store_true', 291 | help='run recursively over directories') 292 | parser.add_argument( 293 | '-d', 294 | '--dry-run', 295 | action='store_true', 296 | help='just print the list of files') 297 | parser.add_argument( 298 | '-i', 299 | '--in-place', 300 | action='store_true', 301 | help='format file instead of printing differences') 302 | parser.add_argument('files', metavar='file', nargs='+') 303 | parser.add_argument( 304 | '-q', 305 | '--quiet', 306 | action='store_true', 307 | help="disable output, useful for the exit code") 308 | parser.add_argument( 309 | '-j', 310 | metavar='N', 311 | type=int, 312 | default=0, 313 | help='run N clang-format jobs in parallel' 314 | ' (default number of cpus + 1)') 315 | parser.add_argument( 316 | '--color', 317 | default='auto', 318 | choices=['auto', 'always', 'never'], 319 | help='show colored diff (default: auto)') 320 | parser.add_argument( 321 | '-e', 322 | '--exclude', 323 | metavar='PATTERN', 324 | action='append', 325 | default=[], 326 | help='exclude paths matching the given glob-like pattern(s)' 327 | ' from recursive search') 328 | parser.add_argument( 329 | '--style', 330 | help='formatting style to apply (LLVM, Google, Chromium, Mozilla, WebKit)') 331 | 332 | args = parser.parse_args() 333 | 334 | # use default signal handling, like diff return SIGINT value on ^C 335 | # https://bugs.python.org/issue14229#msg156446 336 | signal.signal(signal.SIGINT, signal.SIG_DFL) 337 | try: 338 | signal.SIGPIPE 339 | except AttributeError: 340 | # compatibility, SIGPIPE does not exist on Windows 341 | pass 342 | else: 343 | signal.signal(signal.SIGPIPE, signal.SIG_DFL) 344 | 345 | colored_stdout = False 346 | colored_stderr = False 347 | if args.color == 'always': 348 | colored_stdout = True 349 | colored_stderr = True 350 | elif args.color == 'auto': 351 | colored_stdout = sys.stdout.isatty() 352 | colored_stderr = sys.stderr.isatty() 353 | 354 | version_invocation = [args.clang_format_executable, str("--version")] 355 | try: 356 | subprocess.check_call(version_invocation, stdout=DEVNULL) 357 | except subprocess.CalledProcessError as e: 358 | print_trouble(parser.prog, str(e), use_colors=colored_stderr) 359 | return ExitStatus.TROUBLE 360 | except OSError as e: 361 | print_trouble( 362 | parser.prog, 363 | "Command '{}' failed to start: {}".format( 364 | subprocess.list2cmdline(version_invocation), e 365 | ), 366 | use_colors=colored_stderr, 367 | ) 368 | return ExitStatus.TROUBLE 369 | 370 | retcode = ExitStatus.SUCCESS 371 | 372 | excludes = excludes_from_file(DEFAULT_CLANG_FORMAT_IGNORE) 373 | excludes.extend(args.exclude) 374 | 375 | files = list_files( 376 | args.files, 377 | recursive=args.recursive, 378 | exclude=excludes, 379 | extensions=args.extensions.split(',')) 380 | 381 | if not files: 382 | return 383 | 384 | njobs = args.j 385 | if njobs == 0: 386 | njobs = multiprocessing.cpu_count() + 1 387 | njobs = min(len(files), njobs) 388 | 389 | if njobs == 1: 390 | # execute directly instead of in a pool, 391 | # less overhead, simpler stacktraces 392 | it = (run_clang_format_diff_wrapper(args, file) for file in files) 393 | pool = None 394 | else: 395 | pool = multiprocessing.Pool(njobs) 396 | it = pool.imap_unordered( 397 | partial(run_clang_format_diff_wrapper, args), files) 398 | pool.close() 399 | while True: 400 | try: 401 | outs, errs = next(it) 402 | except StopIteration: 403 | break 404 | except DiffError as e: 405 | print_trouble(parser.prog, str(e), use_colors=colored_stderr) 406 | retcode = ExitStatus.TROUBLE 407 | sys.stderr.writelines(e.errs) 408 | except UnexpectedError as e: 409 | print_trouble(parser.prog, str(e), use_colors=colored_stderr) 410 | sys.stderr.write(e.formatted_traceback) 411 | retcode = ExitStatus.TROUBLE 412 | # stop at the first unexpected error, 413 | # something could be very wrong, 414 | # don't process all files unnecessarily 415 | if pool: 416 | pool.terminate() 417 | break 418 | else: 419 | sys.stderr.writelines(errs) 420 | if outs == []: 421 | continue 422 | if not args.quiet: 423 | print_diff(outs, use_color=colored_stdout) 424 | if retcode == ExitStatus.SUCCESS: 425 | retcode = ExitStatus.DIFF 426 | if pool: 427 | pool.join() 428 | return retcode 429 | 430 | 431 | if __name__ == '__main__': 432 | sys.exit(main()) 433 | -------------------------------------------------------------------------------- /.test/lint.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu 3 | 4 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0}); cd ../; pwd) 5 | 6 | 7 | lint_driver () { 8 | pushd $SRC_DIR/src/drivers 9 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse_main.c 10 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse_dev.c 11 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse_spi.c 12 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse_i2c.c 13 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse_gpio.c 14 | python3 $SRC_DIR/.test/bin/run-clang-format.py rtmouse.h 15 | popd 16 | } 17 | 18 | check_driver_version () { 19 | MOD_VER=$(grep MODULE_VERSION $SRC_DIR/src/drivers/rtmouse.c | sed -E 's/MODULE_VERSION\("([0-9.]*)"\);/\1/g') 20 | COMMENT_VER=$(grep '* Version' $SRC_DIR/src/drivers/rtmouse.c | sed -E 's/.*Version: ([0-9.]*)/\1/g') 21 | if [[ "$MOD_VER" != "$COMMENT_VER" ]]; then 22 | echo "The versions do not match." 23 | echo "Module Version: "$MOD_VER 24 | echo "Comment Version: "$COMMENT_VER 25 | exit 1 26 | else 27 | echo "Module Version and Comment Version matched." 28 | fi 29 | } 30 | 31 | 32 | lint_driver 33 | check_driver_version 34 | -------------------------------------------------------------------------------- /50-rtmouse.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="rtmotor*",ACTION=="add",MODE="0666" 2 | KERNEL=="rtlightsensor*",ACTION=="add",MODE="0666" 3 | KERNEL=="rtbuzzer*",ACTION=="add",MODE="0666" 4 | KERNEL=="rtswitch*",ACTION=="add",MODE="0666" 5 | KERNEL=="rtled*",ACTION=="add",MODE="0666" 6 | KERNEL=="rtcounter*",ACTION=="add",MODE="0666" 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | NOTE: The "SampleProgram" directory is licensed under the Apache 2 | License 2.0. See the "LICENSE" file in the directory. 3 | ---------------------------------------------------------------------- 4 | GNU GENERAL PUBLIC LICENSE 5 | Version 2, June 1991 6 | 7 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 8 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 9 | Everyone is permitted to copy and distribute verbatim copies 10 | of this license document, but changing it is not allowed. 11 | 12 | Preamble 13 | 14 | The licenses for most software are designed to take away your 15 | freedom to share and change it. By contrast, the GNU General Public 16 | License is intended to guarantee your freedom to share and change free 17 | software--to make sure the software is free for all its users. This 18 | General Public License applies to most of the Free Software 19 | Foundation's software and to any other program whose authors commit to 20 | using it. (Some other Free Software Foundation software is covered by 21 | the GNU Lesser General Public License instead.) You can apply it to 22 | your programs, too. 23 | 24 | When we speak of free software, we are referring to freedom, not 25 | price. Our General Public Licenses are designed to make sure that you 26 | have the freedom to distribute copies of free software (and charge for 27 | this service if you wish), that you receive source code or can get it 28 | if you want it, that you can change the software or use pieces of it 29 | in new free programs; and that you know you can do these things. 30 | 31 | To protect your rights, we need to make restrictions that forbid 32 | anyone to deny you these rights or to ask you to surrender the rights. 33 | These restrictions translate to certain responsibilities for you if you 34 | distribute copies of the software, or if you modify it. 35 | 36 | For example, if you distribute copies of such a program, whether 37 | gratis or for a fee, you must give the recipients all the rights that 38 | you have. You must make sure that they, too, receive or can get the 39 | source code. And you must show them these terms so they know their 40 | rights. 41 | 42 | We protect your rights with two steps: (1) copyright the software, and 43 | (2) offer you this license which gives you legal permission to copy, 44 | distribute and/or modify the software. 45 | 46 | Also, for each author's protection and ours, we want to make certain 47 | that everyone understands that there is no warranty for this free 48 | software. If the software is modified by someone else and passed on, we 49 | want its recipients to know that what they have is not the original, so 50 | that any problems introduced by others will not reflect on the original 51 | authors' reputations. 52 | 53 | Finally, any free program is threatened constantly by software 54 | patents. We wish to avoid the danger that redistributors of a free 55 | program will individually obtain patent licenses, in effect making the 56 | program proprietary. To prevent this, we have made it clear that any 57 | patent must be licensed for everyone's free use or not licensed at all. 58 | 59 | The precise terms and conditions for copying, distribution and 60 | modification follow. 61 | 62 | GNU GENERAL PUBLIC LICENSE 63 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 64 | 65 | 0. This License applies to any program or other work which contains 66 | a notice placed by the copyright holder saying it may be distributed 67 | under the terms of this General Public License. The "Program", below, 68 | refers to any such program or work, and a "work based on the Program" 69 | means either the Program or any derivative work under copyright law: 70 | that is to say, a work containing the Program or a portion of it, 71 | either verbatim or with modifications and/or translated into another 72 | language. (Hereinafter, translation is included without limitation in 73 | the term "modification".) Each licensee is addressed as "you". 74 | 75 | Activities other than copying, distribution and modification are not 76 | covered by this License; they are outside its scope. The act of 77 | running the Program is not restricted, and the output from the Program 78 | is covered only if its contents constitute a work based on the 79 | Program (independent of having been made by running the Program). 80 | Whether that is true depends on what the Program does. 81 | 82 | 1. You may copy and distribute verbatim copies of the Program's 83 | source code as you receive it, in any medium, provided that you 84 | conspicuously and appropriately publish on each copy an appropriate 85 | copyright notice and disclaimer of warranty; keep intact all the 86 | notices that refer to this License and to the absence of any warranty; 87 | and give any other recipients of the Program a copy of this License 88 | along with the Program. 89 | 90 | You may charge a fee for the physical act of transferring a copy, and 91 | you may at your option offer warranty protection in exchange for a fee. 92 | 93 | 2. You may modify your copy or copies of the Program or any portion 94 | of it, thus forming a work based on the Program, and copy and 95 | distribute such modifications or work under the terms of Section 1 96 | above, provided that you also meet all of these conditions: 97 | 98 | a) You must cause the modified files to carry prominent notices 99 | stating that you changed the files and the date of any change. 100 | 101 | b) You must cause any work that you distribute or publish, that in 102 | whole or in part contains or is derived from the Program or any 103 | part thereof, to be licensed as a whole at no charge to all third 104 | parties under the terms of this License. 105 | 106 | c) If the modified program normally reads commands interactively 107 | when run, you must cause it, when started running for such 108 | interactive use in the most ordinary way, to print or display an 109 | announcement including an appropriate copyright notice and a 110 | notice that there is no warranty (or else, saying that you provide 111 | a warranty) and that users may redistribute the program under 112 | these conditions, and telling the user how to view a copy of this 113 | License. (Exception: if the Program itself is interactive but 114 | does not normally print such an announcement, your work based on 115 | the Program is not required to print an announcement.) 116 | 117 | These requirements apply to the modified work as a whole. If 118 | identifiable sections of that work are not derived from the Program, 119 | and can be reasonably considered independent and separate works in 120 | themselves, then this License, and its terms, do not apply to those 121 | sections when you distribute them as separate works. But when you 122 | distribute the same sections as part of a whole which is a work based 123 | on the Program, the distribution of the whole must be on the terms of 124 | this License, whose permissions for other licensees extend to the 125 | entire whole, and thus to each and every part regardless of who wrote it. 126 | 127 | Thus, it is not the intent of this section to claim rights or contest 128 | your rights to work written entirely by you; rather, the intent is to 129 | exercise the right to control the distribution of derivative or 130 | collective works based on the Program. 131 | 132 | In addition, mere aggregation of another work not based on the Program 133 | with the Program (or with a work based on the Program) on a volume of 134 | a storage or distribution medium does not bring the other work under 135 | the scope of this License. 136 | 137 | 3. You may copy and distribute the Program (or a work based on it, 138 | under Section 2) in object code or executable form under the terms of 139 | Sections 1 and 2 above provided that you also do one of the following: 140 | 141 | a) Accompany it with the complete corresponding machine-readable 142 | source code, which must be distributed under the terms of Sections 143 | 1 and 2 above on a medium customarily used for software interchange; or, 144 | 145 | b) Accompany it with a written offer, valid for at least three 146 | years, to give any third party, for a charge no more than your 147 | cost of physically performing source distribution, a complete 148 | machine-readable copy of the corresponding source code, to be 149 | distributed under the terms of Sections 1 and 2 above on a medium 150 | customarily used for software interchange; or, 151 | 152 | c) Accompany it with the information you received as to the offer 153 | to distribute corresponding source code. (This alternative is 154 | allowed only for noncommercial distribution and only if you 155 | received the program in object code or executable form with such 156 | an offer, in accord with Subsection b above.) 157 | 158 | The source code for a work means the preferred form of the work for 159 | making modifications to it. For an executable work, complete source 160 | code means all the source code for all modules it contains, plus any 161 | associated interface definition files, plus the scripts used to 162 | control compilation and installation of the executable. However, as a 163 | special exception, the source code distributed need not include 164 | anything that is normally distributed (in either source or binary 165 | form) with the major components (compiler, kernel, and so on) of the 166 | operating system on which the executable runs, unless that component 167 | itself accompanies the executable. 168 | 169 | If distribution of executable or object code is made by offering 170 | access to copy from a designated place, then offering equivalent 171 | access to copy the source code from the same place counts as 172 | distribution of the source code, even though third parties are not 173 | compelled to copy the source along with the object code. 174 | 175 | 4. You may not copy, modify, sublicense, or distribute the Program 176 | except as expressly provided under this License. Any attempt 177 | otherwise to copy, modify, sublicense or distribute the Program is 178 | void, and will automatically terminate your rights under this License. 179 | However, parties who have received copies, or rights, from you under 180 | this License will not have their licenses terminated so long as such 181 | parties remain in full compliance. 182 | 183 | 5. You are not required to accept this License, since you have not 184 | signed it. However, nothing else grants you permission to modify or 185 | distribute the Program or its derivative works. These actions are 186 | prohibited by law if you do not accept this License. Therefore, by 187 | modifying or distributing the Program (or any work based on the 188 | Program), you indicate your acceptance of this License to do so, and 189 | all its terms and conditions for copying, distributing or modifying 190 | the Program or works based on it. 191 | 192 | 6. Each time you redistribute the Program (or any work based on the 193 | Program), the recipient automatically receives a license from the 194 | original licensor to copy, distribute or modify the Program subject to 195 | these terms and conditions. You may not impose any further 196 | restrictions on the recipients' exercise of the rights granted herein. 197 | You are not responsible for enforcing compliance by third parties to 198 | this License. 199 | 200 | 7. If, as a consequence of a court judgment or allegation of patent 201 | infringement or for any other reason (not limited to patent issues), 202 | conditions are imposed on you (whether by court order, agreement or 203 | otherwise) that contradict the conditions of this License, they do not 204 | excuse you from the conditions of this License. If you cannot 205 | distribute so as to satisfy simultaneously your obligations under this 206 | License and any other pertinent obligations, then as a consequence you 207 | may not distribute the Program at all. For example, if a patent 208 | license would not permit royalty-free redistribution of the Program by 209 | all those who receive copies directly or indirectly through you, then 210 | the only way you could satisfy both it and this License would be to 211 | refrain entirely from distribution of the Program. 212 | 213 | If any portion of this section is held invalid or unenforceable under 214 | any particular circumstance, the balance of the section is intended to 215 | apply and the section as a whole is intended to apply in other 216 | circumstances. 217 | 218 | It is not the purpose of this section to induce you to infringe any 219 | patents or other property right claims or to contest validity of any 220 | such claims; this section has the sole purpose of protecting the 221 | integrity of the free software distribution system, which is 222 | implemented by public license practices. Many people have made 223 | generous contributions to the wide range of software distributed 224 | through that system in reliance on consistent application of that 225 | system; it is up to the author/donor to decide if he or she is willing 226 | to distribute software through any other system and a licensee cannot 227 | impose that choice. 228 | 229 | This section is intended to make thoroughly clear what is believed to 230 | be a consequence of the rest of this License. 231 | 232 | 8. If the distribution and/or use of the Program is restricted in 233 | certain countries either by patents or by copyrighted interfaces, the 234 | original copyright holder who places the Program under this License 235 | may add an explicit geographical distribution limitation excluding 236 | those countries, so that distribution is permitted only in or among 237 | countries not thus excluded. In such case, this License incorporates 238 | the limitation as if written in the body of this License. 239 | 240 | 9. The Free Software Foundation may publish revised and/or new versions 241 | of the General Public License from time to time. Such new versions will 242 | be similar in spirit to the present version, but may differ in detail to 243 | address new problems or concerns. 244 | 245 | Each version is given a distinguishing version number. If the Program 246 | specifies a version number of this License which applies to it and "any 247 | later version", you have the option of following the terms and conditions 248 | either of that version or of any later version published by the Free 249 | Software Foundation. If the Program does not specify a version number of 250 | this License, you may choose any version ever published by the Free Software 251 | Foundation. 252 | 253 | 10. If you wish to incorporate parts of the Program into other free 254 | programs whose distribution conditions are different, write to the author 255 | to ask for permission. For software which is copyrighted by the Free 256 | Software Foundation, write to the Free Software Foundation; we sometimes 257 | make exceptions for this. Our decision will be guided by the two goals 258 | of preserving the free status of all derivatives of our free software and 259 | of promoting the sharing and reuse of software generally. 260 | 261 | NO WARRANTY 262 | 263 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 264 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 265 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 266 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 267 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 268 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 269 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 270 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 271 | REPAIR OR CORRECTION. 272 | 273 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 274 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 275 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 276 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 277 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 278 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 279 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 280 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 281 | POSSIBILITY OF SUCH DAMAGES. 282 | 283 | END OF TERMS AND CONDITIONS 284 | 285 | How to Apply These Terms to Your New Programs 286 | 287 | If you develop a new program, and you want it to be of the greatest 288 | possible use to the public, the best way to achieve this is to make it 289 | free software which everyone can redistribute and change under these terms. 290 | 291 | To do so, attach the following notices to the program. It is safest 292 | to attach them to the start of each source file to most effectively 293 | convey the exclusion of warranty; and each file should have at least 294 | the "copyright" line and a pointer to where the full notice is found. 295 | 296 | 297 | Copyright (C) 298 | 299 | This program is free software; you can redistribute it and/or modify 300 | it under the terms of the GNU General Public License as published by 301 | the Free Software Foundation; either version 2 of the License, or 302 | (at your option) any later version. 303 | 304 | This program is distributed in the hope that it will be useful, 305 | but WITHOUT ANY WARRANTY; without even the implied warranty of 306 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 307 | GNU General Public License for more details. 308 | 309 | You should have received a copy of the GNU General Public License along 310 | with this program; if not, write to the Free Software Foundation, Inc., 311 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 312 | 313 | Also add information on how to contact you by electronic and paper mail. 314 | 315 | If the program is interactive, make it output a short notice like this 316 | when it starts in an interactive mode: 317 | 318 | Gnomovision version 69, Copyright (C) year name of author 319 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 320 | This is free software, and you are welcome to redistribute it 321 | under certain conditions; type `show c' for details. 322 | 323 | The hypothetical commands `show w' and `show c' should show the appropriate 324 | parts of the General Public License. Of course, the commands you use may 325 | be called something other than `show w' and `show c'; they could even be 326 | mouse-clicks or menu items--whatever suits your program. 327 | 328 | You should also get your employer (if you work as a programmer) or your 329 | school, if any, to sign a "copyright disclaimer" for the program, if 330 | necessary. Here is a sample; alter the names: 331 | 332 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 333 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 334 | 335 | , 1 April 1989 336 | Ty Coon, President of Vice 337 | 338 | This General Public License does not permit incorporating your program into 339 | proprietary programs. If your program is a subroutine library, you may 340 | consider it more useful to permit linking proprietary applications with the 341 | library. If this is what you want to do, use the GNU Lesser General 342 | Public License instead of this License. 343 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RaspberryPiMouse 2 | 3 | [![CI](https://github.com/rt-net/RaspberryPiMouse/actions/workflows/driver-cross-build.yml/badge.svg)](https://github.com/rt-net/RaspberryPiMouse/actions/workflows/driver-cross-build.yml) 4 | 5 | This repository has the source code and kernel objects 6 | for the Raspberry Pi Mouse. 7 | 8 | ## Installation 9 | 10 | Run the following scripts. 11 | 12 | - setting script ([`./utils/set_configs.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash)) 13 | - installation script ([`./utils/build_install.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/build_install.bash)) 14 | 15 | 以下のスクリプトを実行します 16 | - setting script([`./utils/set_configs.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash)) 17 | - installation script([`./utils/build_install.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/build_install.bash)) 18 | 19 | ### for `Raspberry Pi OS`・`Ubuntu` 20 | 21 | 以下のコマンドで本リポジトリをダウンロードし、Raspberry Pi本体の設定を行います。 22 | 23 | ```bash 24 | $ git clone https://github.com/rt-net/RaspberryPiMouse.git 25 | $ cd RaspberryPiMouse/utils 26 | $ ./set_configs.bash 27 | ``` 28 | 29 | Raspberry Piを再起動し、以下のコマンドを実行してビルドに必要なファイルをインストールします。**`Ubuntu`と`Raspberry Pi OS`でコマンドが違います。** 30 | 31 | ```bash 32 | # Ubuntu Serverの場合 33 | $ sudo apt install linux-headers-$(uname -r) build-essential 34 | 35 | # Raspberry Pi OSの場合 36 | $ sudo apt install raspberrypi-kernel-headers build-essential 37 | ``` 38 | 39 | 以下のコマンドでビルドを実行します。 40 | 41 | ```bash 42 | $ cd RaspberryPiMouse/utils 43 | $ ./build_install.bash 44 | ``` 45 | 46 | ### Manual installation 47 | 48 | ```bash 49 | $ git clone https://github.com/rt-net/RaspberryPiMouse.git 50 | $ cd RaspberryPiMouse/src/drivers 51 | $ make 52 | $ sudo insmod rtmouse.ko 53 | ``` 54 | 55 | ## Notes for the installation (ドライバの導入の際の注意) 56 | 57 | 特定の機能の有効化や、プログラムのビルドのために設定が必要な項目があります。以下の設定をご確認ください。 58 | 59 | ※[`./utils/set_configs.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash)を実行すると、[自動で適切な設定に書き換わります]((https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash))。 60 | 61 | 62 | ### for Raspberry Pi OS 63 | 64 | Raspberry Pi OSでは、SPIとI2Cがデフォルトで無効となっているため、有効化する必要があります。 65 | 66 | #### for SPI and I2C 67 | 68 | Enable SPI and I2C functions via `raspi-config` command. 69 | 70 | `raspi-config` コマンドで設定します。 71 | 72 | * SPI機能を「入」にする。 73 | * I2C機能を「入」にする。 74 | 75 | ### for Raspberry Pi 4 76 | 77 | Edit [`rtmouse.c`](https://github.com/rt-net/RaspberryPiMouse/blob/dd0343449951a99b067e24aef3c03ae5ed9ab936/src/drivers/rtmouse.c#L54) to change the defined value `RASPBERRYPI` from`2`to`4`. 78 | 79 | Raspberry Pi 4ではCPUのレジスタがそれまでのRaspberry Piとは異なります([issues#21](https://github.com/rt-net/RaspberryPiMouse/issues/21))。 80 | Raspberry Pi 4で本ドライバを使用する際には`rtmouse.c`の以下の行(2020年4月13日現在の最新版のv2.1.0では[54行目](https://github.com/rt-net/RaspberryPiMouse/blob/dd0343449951a99b067e24aef3c03ae5ed9ab936/src/drivers/rtmouse.c#L54))を`RASPBERRYPI 4`に書き換えてビルドする必要があります。 81 | 82 | ※[`./utils/build_install.bash`](./utils/build_install.bash)を実行すると、Raspberry Piのモデルに合わせて[`rtmouse.c`](./src/drivers/rtmouse.c)が[自動で書き換わります](https://github.com/rt-net/RaspberryPiMouse/blob/a9af4fa2b2a8e34c0f93a6ce5cf88ebd50ff39c2/utils/build_install.raspi4ubuntu.bash#L13-L14)。 83 | 84 | ```c 85 | // define the Raspberry Pi version here 86 | // Raspberry Pi 1 B/A/B+/A+: 1 87 | // Raspberry Pi 2 B : 2 88 | // Raspberry Pi 3 B/A+/B+ : 2 89 | // Raspberry Pi 4 B : 4 90 | #define RASPBERRYPI 2 91 | ``` 92 | 93 | ### for 32-bit OS 94 | 95 | Set 32bit-setting to `/boot/firmware/config.txt`. 96 | 97 | 32-bit版のOSではビルドするために、`/boot/firmware/config.txt`に以下の1行を追加する必要があります。 98 | 99 | ```bash 100 | arm_64bit=0 101 | ``` 102 | 103 | ### デバイスツリーオーバーレイについて 104 | 105 | kernel `5.16`以降では`/boot/firmware/config.txt`に以下の設定を記述し、dtoverlayを設定する必要があります。※[`./utils/set_configs.bash`](https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash)を実行すると、設定は[自動で書き換わります]((https://github.com/rt-net/RaspberryPiMouse/blob/master/utils/set_configs.bash#L35-#L49))。 106 | 107 | ```bash 108 | dtoverlay=anyspi:spi0-0,dev="microchip,mcp3204",speed=1000000 109 | ``` 110 | 111 | ### パルスカウンタについて 112 | 113 | パルスカウンタは値の読み取りにI2Cを使用しています。仕様上は400kHzまでbaudrateを上げることができます(※1)。 114 | I2Cのbaudrateを上げると通信に失敗する場合がある([issues#13](https://github.com/rt-net/RaspberryPiMouse/issues/13))ので、基本的にはI2Cのbaudrateはデフォルト値(※2)から変更して62.5kHzに固定してください。 115 | 116 | According to 117 | [issues#13](https://github.com/rt-net/RaspberryPiMouse/issues/13), 118 | it may be necessary to set the I2C baudrate lower than the default value. 119 | Add a following new line in `/boot/firmware/config.txt` to change the i2c_baudrate to 62.5 kHz. 120 | 121 | `/boot/firmware/config.txt`に以下の1行を追加することでI2Cのbaudrateを62.5kHzに固定することができます。 122 | 123 | ```bash 124 | dtparam=i2c_baudrate=62500 125 | ``` 126 | 127 | ※1 Raspberry Pi 4 Model B(Ubuntu Server `18.04` / `20.04` / `22.04` / `24.04`)を搭載して400kHzで通信できることを確認しています。 128 | ※2 現在設定されているI2Cのbaudrateは以下のコマンドを実行することで確認できます。 129 | ``` 130 | $ printf "%d\n" 0x$(xxd -ps /sys/class/i2c-adapter/i2c-1/of_node/clock-frequency) 131 | ``` 132 | 133 | ## Device files 134 | 135 | For example code of device files, please refer to [SampleProgram](./SampleProgram/README.md). 136 | 137 | デバイスファイルの使用例は[サンプルプログラム](./SampleProgram/README.md)を参考にしてください。 138 | 139 | ### Light sensor x4 (Input) 140 | 141 | Read `/dev/rtlightsensor0` to get proximity (0:far ~ 4095:close) of objects detected by light sensors. 142 | 143 | `/dev/rtlightsensor0`を読み取り、光センサで検出された物体の近接度 (0:遠い ~ 4095:近い)を取得します。 144 | 145 | ```sh 146 | # cat /dev/rtlightsensor0 147 | # Return value: [front right] [right] [left] [front left] 148 | $ cat /dev/rtlightsensor0 149 | 9 2 13 3 150 | ``` 151 | 152 | ### Switch x3 (Input) 153 | 154 | Read `/dev/rtswitch0` ~ `/dev/rtswitch2` to get the switches on/off state. 155 | 156 | `/dev/rtswitch0` ~ `/dev/rtswitch2` を読み取りスイッチのON/OFF状態を取得します。 157 | 158 | ```sh 159 | # cat /dev/rtswitch[0,1] 160 | # Return value: 1(Open), 0(Pressed) 161 | $ cat /dev/rtswitch0 162 | ``` 163 | 164 | ### Buzzer (Output) 165 | 166 | Write 0 ~ 20000 to `/dev/rtbuzzer0` to beep the buzzer. 167 | 168 | `/dev/rtbuzzer0` に0 ~ 20000を書き込みブザーを鳴らします。 169 | 170 | ```sh 171 | # echo 0 ~ 20000(Hz) > /dev/rtbuzzer0 172 | $ echo 440 > /dev/rtbuzzer0 173 | $ echo 0 > /dev/rtbuzzer0 174 | ``` 175 | 176 | ### LED x4 (Output) 177 | 178 | Write 1/0 to `/dev/rtled0` ~ `/dev/rtled3` to turn on/off the LEDs. 179 | 180 | `/dev/rtled0` ~ `/dev/rtled3` に1/0を書き込みLEDを点灯/消灯します。 181 | 182 | ```sh 183 | # echo 0(OFF) or 1(ON) > /dev/rtled[0,1,2,3] 184 | $ echo 1 > /dev/rtled0 185 | $ echo 0 > /dev/rtled1 186 | ``` 187 | 188 | ### Motor enable (Output) 189 | 190 | Write 1/0 to `/dev/rtmotoren0` to enable/disable motors control. 191 | 192 | `/dev/rtmotoren0` に 1/0 を書き込みモータ操作を有効/無効にします。 193 | 194 | ```sh 195 | # echo 0(disable) or 1(enable) > /dev/rtmotoren0 196 | $ echo 1 > /dev/rtmotoren0 197 | ``` 198 | 199 | ### PWM frequency for left/right motor driver (Output) 200 | 201 | Write 0 ~ ±10000 to `/dev/rtmotor_raw_l0` or `/dev/rtmotor_raw_r0` to set PWM frequency for motor drivers. 202 | 203 | ※ 0 ~ ±4 Hz will be reset to 0 Hz. 204 | 205 | `/dev/rtmotor_raw_l0` または `/dev/rtmotor_raw_r0` に 0 ~ ±10000 を書き込み、モータドライバへのPWM周波数を設定します。 206 | 207 | ※ 0 ~ ±4 Hzは0Hzへリセットされます 208 | 209 | ```sh 210 | # echo 0 ~ ±10000(Hz) > /dev/rtmotor_raw_[l0, r0] 211 | $ echo 1 > /dev/rtmotoren0 212 | $ echo 400 > /dev/rtmotor_raw_l0 213 | ``` 214 | 215 | ### PWM frequencies and drive duration (Output) 216 | 217 | Write left and right PWM frequencies and drive duration to `/dev/rtmotor0` to drive both motors. 218 | 219 | `/dev/rtmotor0`に左右のPWM周波数と動作時間を書き込み、左右のモータを回します。 220 | 221 | ```sh 222 | # echo [left_freq Hz] [right_freq Hz] [duration ms] > /dev/rtmotor0 223 | $ echo 1 > /dev/rtmotoren0 224 | $ echo 400 800 1000 > /dev/rtmotor0 225 | ``` 226 | 227 | ### Pulse counter x2 (Input/Output) 228 | 229 | Read `/dev/rtcounter_*` to get pulse counts of PWM for motor drivers or write values to reset counts. 230 | 231 | `/dev/rtcounter_*`を読み取りモータドライバへのPWMパルス数を取得します。また、値を書き込みカウントをリセットします。 232 | 233 | - unsigned counters : `/dev/rtcounter_l0`, `/dev/rtcounter_r0` 234 | - signed counters : `/dev/rtcounter_l1`, `/dev/rtcounter_r1` 235 | 236 | ```sh 237 | # cat /dev/rtcounter_[l0, r0] 238 | # Return value: 0 ~ 65565 (counts of PWM pulse) 239 | # cat /dev/rtcounter_[l1, r1] 240 | # Return value: -32767 ~ 32767 (counts of PWM pulse) 241 | $ cat /dev/rtcounter_l0 242 | 1104 243 | $ echo 0 > /dev/rtcounter_l0 244 | $ cat /dev/rtcounter_l0 245 | 0 246 | ``` 247 | 248 | ## その他 249 | 250 | その他のよくある質問については[wiki](https://github.com/rt-net/RaspberryPiMouse/wiki#%E3%82%88%E3%81%8F%E3%81%82%E3%82%8B%E8%B3%AA%E5%95%8F)にまとめています。 251 | 252 | ## 日経Linux連載 253 | 254 | 連載(Raspberry Piで始めるかんたんロボット製作)で上田氏が書いた 255 | シェルスクリプトは下記にあります。 256 | 257 | https://github.com/ryuichiueda/RPiM 258 | 259 | 260 | ## License 261 | 262 | This repository except for `SampleProgram` directory is licensed under the [GPL-2.0-only](https://spdx.org/licenses/GPL-2.0-only.html) License, see [LICENSE](./LICENSE). 263 | 264 | `SampleProgram` directory is licensed under the Apache 2.0 License, see [SampleProgram / LICENSE](./SampleProgram/LICENSE). 265 | 266 | このリポジトリは`SampleProgram`ディレクトリを除き[GPL-2.0-only](https://spdx.org/licenses/GPL-2.0-only.html)ライセンスで公開されています。詳細は[LICENSE](./LICENSE)を確認してください。 267 | 268 | `SampleProgram`ディレクトリは[Apache-2.0](https://spdx.org/licenses/Apache-2.0.html)ライセンスで公開されています。詳細は[SampleProgram / LICENSE](./SampleProgram/LICENSE)を確認してください。 269 | 270 | ### Includings 271 | 272 | This repository contains the code of the repository shown below. 273 | 274 | このリポジトリは以下に示すリポジトリのコードを一部含みます。 275 | 276 | * [take-iwiw/DeviceDriverLesson](https://github.com/take-iwiw/DeviceDriverLesson) 277 | * GPL/BSD License 278 | * [mcp3204.c in Raspberry Piで学ぶARMデバイスドライバープログラミング](http://www.socym.co.jp/support/s-940#ttlDownload) 279 | * GPL v2 License 280 | * [RPi-Distro/raspi-gpio](https://github.com/RPi-Distro/raspi-gpio) 281 | * The 3-Clause BSD License 282 | -------------------------------------------------------------------------------- /SampleProgram/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: Google 2 | IndentWidth: 4 -------------------------------------------------------------------------------- /SampleProgram/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /SampleProgram/README.md: -------------------------------------------------------------------------------- 1 | # Sample Program 2 | 3 | このディレクトリにはLED、スイッチ、ブザーなどのRaspberryPiMouseの周辺機器を使うサンプルコードがあります。 4 | 5 | This directory contains examples how to use RaspberryPiMouse's peripherals like LEDs, switches, buzzer, etc. 6 | 7 | このディレクトリはApache 2.0ライセンスで公開されています。詳細は[SampleProgram / LICENSE](./LICENSE)を確認してください。 8 | 9 | This directory is licensed under the Apache 2.0 License, see [SampleProgram / LICENSE](./LICENSE). 10 | 11 | 12 | # How To Use 13 | 14 | 各機能ごとにShell Script、C、Pythonで書かれたサンプルコードを用意しています。 15 | 16 | Each peripheral example has sample code files written Shell Script, C and Python. 17 | 18 | ## Shell Script 19 | 20 | ```sh 21 | $ bash step1.sh 22 | 23 | Ctrl-c を押して終了してください。 24 | Press [Ctrl-c] to terminate. 25 | ``` 26 | 27 | ## C 28 | 29 | サンプル実行前に、gccでコンパイルします。 30 | 31 | Compile an example code via gcc command before execution. 32 | 33 | ```sh 34 | $ gcc step1.c -o step1 35 | $ ./step1 36 | 37 | Ctrl-c を押して終了してください。 38 | Press [Ctrl-c] to terminate. 39 | ``` 40 | 41 | ## Python 42 | 43 | ```sh 44 | $ python3 step1.py 45 | 46 | Ctrl-c を押して終了してください。 47 | Press [Ctrl-c] to terminate. 48 | ``` 49 | 50 | # Step1 51 | 52 | LED0~LED3が点滅します。 53 | 54 | The LED0 ~ LED3 blinks. 55 | 56 | # Step2 57 | 58 | キーボード入力でブザーを鳴らします。 59 | 入力キーと音階のペアは[./SCALE](./SCALE)を参照してください。 60 | 61 | '0'を入力するとブザーが止まります。 62 | 'c'を入力するとプログラムが終了します。(Shell ScriptではCtrl-cで終了します。) 63 | 64 | Beep the buzzer with keyboard input. 65 | Refer to the [./SCALE](./SCALE) file for the pairs of input characters and scales. 66 | 67 | Press '0' to stop beeping. 68 | Press 'c' to terminate the program. (Press Ctrl-c for the Shell Script.) 69 | 70 | # Step3 71 | 72 | スイッチを押してLEDを点消灯します。 73 | 組み合わせは次のとおりです。 74 | 75 | Turn on/off LEDs by the switches. 76 | The combination of LEDs and switches are defined as bellow. 77 | 78 | - SW0 : LED3 79 | - SW1 : LED1 & LED2 80 | - SW2 : LED0 81 | 82 | # Step4 83 | 84 | モータを回して右旋回、左旋回します。 85 | 86 | Drive the motors to rotate clockwise and counter-clockwise. 87 | 88 | # Step5 89 | 90 | ライトセンサの値を読み込みます。 91 | 92 | Read the lightsensors values. 93 | 94 | # Step6 95 | 96 | モータを回して、パルスカウンタの値を読み込みます。 97 | 98 | Drive the motors and read the pulse counters values. 99 | -------------------------------------------------------------------------------- /SampleProgram/RemoCon_Step1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xv 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | trap 2 18 | 19 | sudo sixad -start & 20 | 21 | 22 | set +xv 23 | while true ; do 24 | if grep -q 0 /dev/rtswitch0 ; then 25 | sleep 0.1 26 | while grep -q 0 /dev/rtswitch0 ; do 27 | sleep 0.1 28 | done 29 | sudo python /home/pi/bbb.py 30 | break 31 | fi 32 | if grep -q 0 /dev/rtswitch1 ; then 33 | sleep 0.1 34 | while grep -q 0 /dev/rtswitch1 ; do 35 | sleep 0.1 36 | done 37 | break; 38 | fi 39 | if grep -q 0 /dev/rtswitch2 ; then 40 | sleep 0.1 41 | while grep -q 0 /dev/rtswitch2 ; do 42 | sleep 0.1 43 | done 44 | break 45 | fi 46 | 47 | echo 1 | tee /dev/rtled? 48 | sleep 0.5 49 | echo 0 | tee /dev/rtled? 50 | sleep 0.5 51 | done 52 | set -xv 53 | 54 | 55 | -------------------------------------------------------------------------------- /SampleProgram/RemoCon_for_PS3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import sys 18 | file = open('/dev/input/js0','r') 19 | data = [] 20 | led0 = open('/dev/rtled0','a') 21 | led1 = open('/dev/rtled1','a') 22 | led2 = open('/dev/rtled2','a') 23 | led3 = open('/dev/rtled3','a') 24 | rmotor = open('/dev/rtmotor_raw_r0','a') 25 | lmotor = open('/dev/rtmotor_raw_l0','a') 26 | motoren = open('/dev/rtmotoren0','a') 27 | buzzer = open('/dev/rtbuzzer0','a') 28 | straight = 0 29 | curbe =0 30 | 31 | while 1: 32 | for character in file.read(1): 33 | data += ['%02X' % ord(character)] 34 | if len(data) == 8: 35 | if data[6] == '01': 36 | if data[4] == '01': 37 | if data[7] == '0F': 38 | led3.write("1") 39 | elif data[7] == '0E': 40 | led2.write("1") 41 | elif data[7] == '0D': 42 | led1.write("1") 43 | elif data[7] == '0C': 44 | led0.write("1") 45 | elif data[7] == '04': 46 | print >> motoren,1 47 | print >> rmotor,500 48 | print >> lmotor,500 49 | elif data[7] == '06': 50 | print >> motoren,1 51 | print >> rmotor,-500 52 | print >> lmotor,-500 53 | elif data[7] == '05': 54 | print >> motoren,1 55 | print >> rmotor,-500 56 | print >> lmotor,500 57 | elif data[7] == '07': 58 | print >> motoren,1 59 | print >> rmotor,500 60 | print >> lmotor,-500 61 | elif data[7] == '00' : 62 | print >> buzzer,440 63 | elif data[4] == '00': 64 | if data[7] == '0F': 65 | led3.write("0") 66 | elif data[7] == '0E': 67 | led2.write("0") 68 | elif data[7] == '0D': 69 | led1.write("0") 70 | elif data[7] == '0C': 71 | led0.write("0") 72 | elif data[7] == '04': 73 | print >> motoren,0 74 | elif data[7] == '06': 75 | print >> motoren,0 76 | elif data[7] == '05': 77 | print >> motoren,0 78 | elif data[7] == '07': 79 | print >> motoren,0 80 | elif data[7] == '00' : 81 | print >> buzzer,0 82 | straight=0 83 | curbe=0 84 | elif data[6] == '02':#analog 85 | if data[7] == '01':#left 86 | print >> motoren,1 87 | if int(data[5],16) > 127: 88 | if int(data[5],16) < 252: 89 | straight = (255 - int(data[5],16)) * 5 90 | print "straight %d" % straight 91 | print >> rmotor,int(straight * (127 - curbe) / 50) 92 | print >> lmotor,int(straight * (127 + curbe) / 50) 93 | elif int(data[5],16) > 3: 94 | straight = -(int(data[5],16)) * 5 95 | print "straight %d" % straight 96 | print >> rmotor,int(straight * (127 - curbe ) / 50) 97 | print >> lmotor,int(straight * (127 + curbe) / 50) 98 | else : 99 | print >> motoren,0 100 | print >> lmotor,0 101 | print >> rmotor,0 102 | straight=0 103 | elif data[7] == '02':#right 104 | print >> motoren,1 105 | if int(data[5],16) > 127:#left 106 | if int(data[5],16) < 252: 107 | curbe = -(255 - int(data[5],16)) 108 | print "curbe %d" % curbe 109 | print >> rmotor,int(straight * (127 -curbe) / 50) 110 | print >> lmotor,int(straight * (127 + curbe) /50) 111 | elif int(data[5],16) > 3: 112 | curbe = (int(data[5],16)) 113 | print "curbe %d" % curbe 114 | print >> rmotor,int(straight * (127 - curbe) / 50) 115 | print >> lmotor,int(straight * (127 + curbe) / 50) 116 | else : 117 | curbe=0 118 | led3.flush() 119 | led2.flush() 120 | led1.flush() 121 | led0.flush() 122 | motoren.flush() 123 | rmotor.flush() 124 | lmotor.flush() 125 | buzzer.flush() 126 | data = [] 127 | -------------------------------------------------------------------------------- /SampleProgram/SCALE: -------------------------------------------------------------------------------- 1 | off 0 0 2 | DO 261 a 3 | DO# 277 w 4 | re 293 s 5 | re# 311 e 6 | mi 329 d 7 | fa 349 f 8 | fa# 370 t 9 | so 392 g 10 | so# 415 y 11 | ra 440 h 12 | ra# 466 u 13 | shi 493 j 14 | do2 523 k 15 | 16 | -------------------------------------------------------------------------------- /SampleProgram/step1.c: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | int main(void) { 19 | int led[4]; 20 | int i; 21 | 22 | led[0] = open("/dev/rtled0", O_WRONLY); 23 | led[1] = open("/dev/rtled1", O_WRONLY); 24 | led[2] = open("/dev/rtled2", O_WRONLY); 25 | led[3] = open("/dev/rtled3", O_WRONLY); 26 | 27 | while (1) { 28 | for (i = 0; i < 4; i++) { 29 | write(led[i], "1", 1); 30 | } 31 | usleep(500 * 1000); 32 | for (i = 0; i < 4; i++) { 33 | write(led[i], "0", 1); 34 | } 35 | usleep(500 * 1000); 36 | } 37 | for (i = 0; i < 4; i++) { 38 | close(led[i]); 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /SampleProgram/step1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import time 18 | import sys 19 | 20 | files = ["/dev/rtled0", "/dev/rtled1", "/dev/rtled2", "/dev/rtled3"] 21 | 22 | while 1: 23 | for filename in files: 24 | with open(filename, 'w') as f: 25 | f.write("1") 26 | time.sleep(0.5) 27 | for filename in files: 28 | with open(filename, 'w') as f: 29 | f.write("0") 30 | time.sleep(0.5) 31 | -------------------------------------------------------------------------------- /SampleProgram/step1.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | while true 18 | do 19 | echo 1 | tee /dev/rtled? 20 | sleep 0.5 21 | echo 0 | tee /dev/rtled? 22 | sleep 0.5 23 | done 24 | 25 | -------------------------------------------------------------------------------- /SampleProgram/step2.c: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | int _Getch(void) { 21 | int ch; 22 | system("stty -echo -icanon min 1 time 0"); 23 | ch = getchar(); 24 | system("stty echo icanon"); 25 | return ch; 26 | } 27 | 28 | int main(void) { 29 | int buzzer = open("/dev/rtbuzzer0", O_WRONLY); 30 | int c = 1; 31 | 32 | while (c) { 33 | switch (_Getch()) { 34 | case '0': // off 35 | write(buzzer, "0", 2); 36 | break; 37 | case 'a': // do 38 | write(buzzer, "261", 4); 39 | break; 40 | case 'w': // do# 41 | write(buzzer, "277", 4); 42 | break; 43 | case 's': // re 44 | write(buzzer, "293", 4); 45 | break; 46 | case 'e': // re# 47 | write(buzzer, "311", 4); 48 | break; 49 | case 'd': // mi 50 | write(buzzer, "329", 4); 51 | break; 52 | case 'f': // fa 53 | write(buzzer, "349", 4); 54 | break; 55 | case 't': // fa# 56 | write(buzzer, "370", 4); 57 | break; 58 | case 'g': // so 59 | write(buzzer, "392", 4); 60 | break; 61 | case 'y': // so# 62 | write(buzzer, "415", 4); 63 | break; 64 | case 'h': // ra 65 | write(buzzer, "440", 4); 66 | break; 67 | case 'u': // ra# 68 | write(buzzer, "466", 4); 69 | break; 70 | case 'j': // shi 71 | write(buzzer, "493", 4); 72 | break; 73 | case 'k': // do2 74 | write(buzzer, "523", 4); 75 | break; 76 | case 'c': 77 | write(buzzer, "0", 2); 78 | c = 0; 79 | break; 80 | } 81 | } 82 | close(buzzer); 83 | return 0; 84 | } 85 | -------------------------------------------------------------------------------- /SampleProgram/step2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import sys 18 | import tty 19 | import termios 20 | 21 | 22 | class _Getch: 23 | def __init__(self): 24 | pass 25 | 26 | def __call__(self): 27 | fd = sys.stdin.fileno() 28 | old_settings = termios.tcgetattr(fd) 29 | try: 30 | tty.setraw(sys.stdin.fileno()) 31 | ch = sys.stdin.read(1) 32 | finally: 33 | termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) 34 | return ch 35 | 36 | 37 | freq_dict = { 38 | "0": "0", "a": "261", "w": "277", "s": "293", "e": "311", "d": "329", 39 | "f": "349", "t": "370", "g": "392", "y": "415", "h": "440", "u": "466", 40 | "j": "493", "k": "523"} 41 | 42 | while 1: 43 | getch = _Getch() 44 | key = getch() 45 | if key == "c": 46 | break 47 | if key in freq_dict: 48 | with open('/dev/rtbuzzer0', 'w') as f: 49 | f.write(freq_dict[key]) 50 | -------------------------------------------------------------------------------- /SampleProgram/step2.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | while read -N 1 b ; do 18 | awk -v "t=$b" '$3==t{print $2}' SCALE > /dev/rtbuzzer0 19 | done 20 | 21 | -------------------------------------------------------------------------------- /SampleProgram/step3.c: -------------------------------------------------------------------------------- 1 | // Copyright 2016-2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | char get_SW0(void) { 19 | char buf[2]; 20 | int SW0; 21 | SW0 = open("/dev/rtswitch0", O_RDONLY); 22 | read(SW0, buf, 2); 23 | close(SW0); 24 | return buf[0]; 25 | } 26 | 27 | char get_SW1(void) { 28 | char buf[2]; 29 | int SW1; 30 | SW1 = open("/dev/rtswitch1", O_RDONLY); 31 | read(SW1, buf, 2); 32 | close(SW1); 33 | return buf[0]; 34 | } 35 | 36 | char get_SW2(void) { 37 | char buf[2]; 38 | int SW2; 39 | SW2 = open("/dev/rtswitch2", O_RDONLY); 40 | read(SW2, buf, 2); 41 | close(SW2); 42 | return buf[0]; 43 | } 44 | 45 | int main(void) { 46 | int state0, state1, state2; 47 | int LED0, LED1, LED2, LED3; 48 | 49 | LED0 = open("/dev/rtled0", O_WRONLY); 50 | LED1 = open("/dev/rtled1", O_WRONLY); 51 | LED2 = open("/dev/rtled2", O_WRONLY); 52 | LED3 = open("/dev/rtled3", O_WRONLY); 53 | 54 | state0 = state1 = state2 = 0; 55 | 56 | while (1) { 57 | if (get_SW0() == '0') { 58 | usleep(10000); 59 | while (get_SW0() == '0') 60 | ; 61 | usleep(10000); 62 | state0 = (state0 + 1) & 0x01; 63 | if (state0 == 0) { 64 | write(LED3, "0", 1); 65 | } else { 66 | write(LED3, "1", 1); 67 | } 68 | } 69 | if (get_SW1() == '0') { 70 | usleep(10000); 71 | while (get_SW1() == '0') 72 | ; 73 | usleep(10000); 74 | state1 = (state1 + 1) & 0x01; 75 | if (state1 == 0) { 76 | write(LED2, "0", 1); 77 | write(LED1, "0", 1); 78 | } else { 79 | write(LED2, "1", 1); 80 | write(LED1, "1", 1); 81 | } 82 | } 83 | if (get_SW2() == '0') { 84 | usleep(10000); 85 | while (get_SW2() == '0') 86 | ; 87 | usleep(10000); 88 | state2 = (state2 + 1) & 0x01; 89 | if (state2 == 0) { 90 | write(LED0, "0", 1); 91 | } else { 92 | write(LED0, "1", 1); 93 | } 94 | } 95 | } 96 | return 0; 97 | } 98 | -------------------------------------------------------------------------------- /SampleProgram/step3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import time 18 | 19 | state0 = state1 = state2 = 0 20 | 21 | while 1: 22 | with open("/dev/rtswitch0", "r") as f: 23 | if f.readline() == "0\n": 24 | time.sleep(0.1) 25 | while 1: 26 | with open("/dev/rtswitch0", "r") as f: 27 | if f.readline() != "0\n": 28 | break 29 | time.sleep(0.1) 30 | state0 = (state0 + 1) & 1 31 | with open("/dev/rtled3", "w") as f: 32 | f.write(str(state0)) 33 | with open("/dev/rtswitch1", "r") as f: 34 | if f.readline() == "0\n": 35 | time.sleep(0.1) 36 | while 1: 37 | with open("/dev/rtswitch1", "r") as f: 38 | if f.readline() != "0\n": 39 | break 40 | time.sleep(0.1) 41 | state1 = (state1 + 1) & 1 42 | with open("/dev/rtled2", "w") as f: 43 | f.write(str(state1)) 44 | with open("/dev/rtled1", "w") as f: 45 | f.write(str(state1)) 46 | with open("/dev/rtswitch2", "r") as f: 47 | if f.readline() == "0\n": 48 | time.sleep(0.1) 49 | while 1: 50 | with open("/dev/rtswitch2", "r") as f: 51 | if f.readline() != "0\n": 52 | break 53 | time.sleep(0.1) 54 | state2 = (state2 + 1) & 1 55 | with open("/dev/rtled0", "w") as f: 56 | f.write(str(state2)) 57 | -------------------------------------------------------------------------------- /SampleProgram/step3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2016-2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | state0=0 18 | state1=0 19 | state2=0 20 | 21 | while true ; do 22 | if grep -q 0 /dev/rtswitch0 ; then 23 | sleep 0.1 24 | while grep -q 0 /dev/rtswitch0 ; do 25 | sleep 0.1 26 | done 27 | state0=`expr $state0 + 1` 28 | state0=`expr $state0 % 2` 29 | echo $state0 > /dev/rtled3 30 | fi 31 | if grep -q 0 /dev/rtswitch1 ; then 32 | sleep 0.1 33 | while grep -q 0 /dev/rtswitch1 ; do 34 | sleep 0.1 35 | done 36 | state1=`expr $state1 + 1` 37 | state1=`expr $state1 % 2` 38 | echo $state1 > /dev/rtled2 39 | echo $state1 > /dev/rtled1 40 | fi 41 | if grep -q 0 /dev/rtswitch2 ; then 42 | sleep 0.1 43 | while grep -q 0 /dev/rtswitch2 ; do 44 | sleep 0.1 45 | done 46 | state2=`expr $state2 + 1` 47 | state2=`expr $state2 % 2` 48 | echo $state2 > /dev/rtled0 49 | fi 50 | done 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /SampleProgram/step4.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | int main(void) { 20 | int motoren = open("/dev/rtmotoren0", O_WRONLY); 21 | int motor_l = open("/dev/rtmotor_raw_l0", O_WRONLY); 22 | int motor_r = open("/dev/rtmotor_raw_r0", O_WRONLY); 23 | int motor = open("/dev/rtmotor0", O_WRONLY); 24 | 25 | printf("Motor On\n"); 26 | write(motoren, "1", 1); 27 | usleep(500 * 1000); 28 | 29 | printf("Rotate counter-clockwise\n"); 30 | write(motor_l, "-400", 5); 31 | write(motor_r, "400", 5); 32 | usleep(500 * 1000); 33 | 34 | write(motor_l, "0", 5); 35 | write(motor_r, "0", 5); 36 | usleep(500 * 1000); 37 | 38 | printf("Rotate clockwise\n"); 39 | write(motor_l, "400", 5); 40 | write(motor_r, "-400", 5); 41 | usleep(500 * 1000); 42 | 43 | write(motor_l, "0", 5); 44 | write(motor_r, "0", 5); 45 | usleep(500 * 1000); 46 | 47 | printf("Rotate clockwise\n"); 48 | write(motor, "400 -400 500", 15); 49 | usleep(500 * 1000); 50 | 51 | printf("Rotate counter-clockwise\n"); 52 | write(motor, "-400 400 500", 15); 53 | 54 | printf("Motor Off\n"); 55 | write(motoren, "0", 1); 56 | 57 | close(motoren); 58 | close(motor_l); 59 | close(motor_r); 60 | close(motor); 61 | return 0; 62 | } 63 | -------------------------------------------------------------------------------- /SampleProgram/step4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import time 18 | import sys 19 | 20 | filename_motoren = "/dev/rtmotoren0" 21 | filename_motor_r = "/dev/rtmotor_raw_r0" 22 | filename_motor_l = "/dev/rtmotor_raw_l0" 23 | filename_motor = "/dev/rtmotor0" 24 | 25 | SPEED = "400" 26 | TIME_MS = "500" 27 | 28 | def motor_drive(freq_l="0", freq_r="0"): 29 | with open(filename_motor_l, 'w') as f: 30 | f.write(freq_l) 31 | with open(filename_motor_r, 'w') as f: 32 | f.write(freq_r) 33 | 34 | print("Motor On") 35 | with open(filename_motoren, 'w') as f: 36 | f.write("1") 37 | time.sleep(0.5) 38 | 39 | print("Rotate counter-clockwise") 40 | motor_drive("-"+SPEED, SPEED) 41 | time.sleep(0.5) 42 | 43 | motor_drive("0", "0") 44 | time.sleep(0.5) 45 | 46 | print("Rotate clockwise") 47 | motor_drive(SPEED, "-"+SPEED) 48 | time.sleep(0.5) 49 | 50 | motor_drive("0", "0") 51 | time.sleep(0.5) 52 | 53 | print("Rotate clockwise") 54 | with open(filename_motor, 'w') as f: 55 | f.write(SPEED+" -"+SPEED+" "+TIME_MS) 56 | 57 | time.sleep(0.5) 58 | 59 | print("Rotate counter-clockwise") 60 | with open(filename_motor, 'w') as f: 61 | f.write("-"+SPEED+" "+SPEED+" "+TIME_MS) 62 | 63 | print("Motor Off") 64 | with open(filename_motoren, 'w') as f: 65 | f.write("0") 66 | -------------------------------------------------------------------------------- /SampleProgram/step4.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | MOTOR_EN=/dev/rtmotoren0 18 | MOTOR_R=/dev/rtmotor_raw_r0 19 | MOTOR_L=/dev/rtmotor_raw_l0 20 | MOTOR=/dev/rtmotor0 21 | 22 | SPEED=400 23 | TIME_MS=500 24 | 25 | echo "Motor On" 26 | echo 1 > $MOTOR_EN 27 | sleep 0.5 28 | 29 | echo "Rotate counter-clockwise" 30 | echo -$SPEED > $MOTOR_L 31 | echo $SPEED > $MOTOR_R 32 | sleep 0.5 33 | 34 | echo 0 > $MOTOR_L 35 | echo 0 > $MOTOR_R 36 | sleep 0.5 37 | 38 | echo "Rotate clockwise" 39 | echo $SPEED > $MOTOR_L 40 | echo -$SPEED > $MOTOR_R 41 | sleep 0.5 42 | 43 | echo 0 > $MOTOR_L 44 | echo 0 > $MOTOR_R 45 | sleep 0.5 46 | 47 | echo "Rotate clockwise" 48 | echo $SPEED -$SPEED $TIME_MS > $MOTOR 49 | sleep 0.5 50 | 51 | echo "Rotate counter-clockwise" 52 | echo -$SPEED $SPEED $TIME_MS > $MOTOR 53 | 54 | echo "Motor Off" 55 | echo 0 > $MOTOR_EN 56 | -------------------------------------------------------------------------------- /SampleProgram/step5.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | int main(void) { 20 | int buff_size = 256; 21 | FILE *fp; 22 | 23 | char buff[buff_size]; 24 | while (1) { 25 | if ((fp = fopen("/dev/rtlightsensor0", "r")) != NULL) { 26 | while (fgets(buff, buff_size, fp) != NULL) { 27 | printf("%s", buff); 28 | } 29 | } 30 | fclose(fp); 31 | usleep(500 * 1000); 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /SampleProgram/step5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import time 18 | 19 | while 1: 20 | with open("/dev/rtlightsensor0", 'r') as f: 21 | print(f.read().strip()) 22 | time.sleep(0.5) 23 | 24 | -------------------------------------------------------------------------------- /SampleProgram/step5.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | while true 18 | do 19 | cat /dev/rtlightsensor0 20 | sleep 0.5 21 | done 22 | 23 | -------------------------------------------------------------------------------- /SampleProgram/step6.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 RT Corporation 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define FILE_MOTOREN "/dev/rtmotoren0" 22 | #define FILE_MOTOR_L "/dev/rtmotor_raw_l0" 23 | #define FILE_MOTOR_R "/dev/rtmotor_raw_r0" 24 | #define FILE_COUNT_L "/dev/rtcounter_l0" 25 | #define FILE_COUNT_R "/dev/rtcounter_r0" 26 | #define BUFF_SIZE 256 27 | 28 | void motor_drive(char *freq_l, char *freq_r) { 29 | FILE *motor_l, *motor_r; 30 | if ((motor_l = fopen(FILE_MOTOR_L, "w")) != NULL && 31 | (motor_r = fopen(FILE_MOTOR_R, "w")) != NULL) { 32 | fputs(freq_l, motor_l); 33 | fputs(freq_r, motor_r); 34 | } 35 | fclose(motor_l); 36 | fclose(motor_r); 37 | } 38 | 39 | void delete_newline(char *str) { 40 | char *p; 41 | 42 | if ((p = strchr(str, '\n')) != NULL) { 43 | *p = '\0'; 44 | } 45 | } 46 | 47 | void print_counter(const int timeout) { 48 | FILE *count_l, *count_r; 49 | char buff_l[BUFF_SIZE]; 50 | char buff_r[BUFF_SIZE]; 51 | 52 | time_t start = time(NULL); 53 | int elapsed_time = 0; 54 | 55 | while (elapsed_time < timeout) { 56 | if ((count_l = fopen(FILE_COUNT_L, "r")) != NULL && 57 | (count_r = fopen(FILE_COUNT_R, "r")) != NULL) { 58 | while (fgets(buff_l, BUFF_SIZE, count_l) != NULL) { 59 | } 60 | while (fgets(buff_r, BUFF_SIZE, count_r) != NULL) { 61 | } 62 | delete_newline(buff_l); 63 | delete_newline(buff_r); 64 | printf("count_l:%s, count_r:%s\n", buff_l, buff_r); 65 | } 66 | fclose(count_l); 67 | fclose(count_r); 68 | 69 | elapsed_time = (int)(time(NULL) - start); 70 | } 71 | } 72 | 73 | void reset_counters_and_motors(void) { 74 | FILE *count_l, *count_r; 75 | 76 | motor_drive("0", "0"); 77 | 78 | printf("Reset counter\n"); 79 | if ((count_l = fopen(FILE_COUNT_L, "w")) != NULL && 80 | (count_r = fopen(FILE_COUNT_R, "w")) != NULL) { 81 | fputs("0", count_l); 82 | fputs("0", count_r); 83 | } 84 | fclose(count_l); 85 | fclose(count_r); 86 | } 87 | 88 | int main(void) { 89 | int motoren = open("/dev/rtmotoren0", O_WRONLY); 90 | // int motor_l = open("/dev/rtmotor_raw_l0",O_WRONLY); 91 | 92 | printf("Motor On\n"); 93 | write(motoren, "1", 1); 94 | 95 | printf("Rotate left motor\n"); 96 | usleep(500 * 1000); 97 | motor_drive("400", "0"); 98 | print_counter(2); 99 | reset_counters_and_motors(); 100 | 101 | printf("Rotate right motor\n"); 102 | usleep(500 * 1000); 103 | motor_drive("0", "400"); 104 | print_counter(2); 105 | reset_counters_and_motors(); 106 | 107 | printf("Move forward\n"); 108 | usleep(500 * 1000); 109 | motor_drive("400", "400"); 110 | print_counter(2); 111 | reset_counters_and_motors(); 112 | 113 | printf("Move backward\n"); 114 | usleep(500 * 1000); 115 | motor_drive("-400", "-400"); 116 | print_counter(2); 117 | reset_counters_and_motors(); 118 | 119 | printf("Motor Off\n"); 120 | write(motoren, "0", 1); 121 | 122 | close(motoren); 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /SampleProgram/step6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import time 18 | import sys 19 | 20 | filename_motoren = "/dev/rtmotoren0" 21 | filename_motor_r = "/dev/rtmotor_raw_r0" 22 | filename_motor_l = "/dev/rtmotor_raw_l0" 23 | filename_motor = "/dev/rtmotor0" 24 | filename_count_r = "/dev/rtcounter_r0" 25 | filename_count_l = "/dev/rtcounter_l0" 26 | 27 | SPEED = "400" 28 | 29 | 30 | def motor_drive(freq_l="0", freq_r="0"): 31 | with open(filename_motor_l, 'w') as f: 32 | f.write(freq_l) 33 | with open(filename_motor_r, 'w') as f: 34 | f.write(freq_r) 35 | 36 | 37 | def print_counter(timeout=2.0): 38 | start = time.time() 39 | while time.time() - start < timeout: 40 | count_r = count_l = 0 41 | with open(filename_count_l, 'r') as f: 42 | count_l = f.read().strip() 43 | with open(filename_count_r, 'r') as f: 44 | count_r = f.read().strip() 45 | print("count_l:" + count_l + ", count_r:" + count_r) 46 | 47 | 48 | def reset_counters_and_motors(): 49 | motor_drive("0", "0") 50 | print("Reset counter") 51 | with open(filename_count_l, 'w') as f: 52 | f.write("0") 53 | with open(filename_count_r, 'w') as f: 54 | f.write("0") 55 | print_counter(0) 56 | 57 | 58 | print("Motor On") 59 | with open(filename_motoren, 'w') as f: 60 | f.write("1") 61 | 62 | print("Rotate left motor") 63 | time.sleep(0.5) 64 | motor_drive(SPEED, "0") 65 | print_counter(2.0) 66 | reset_counters_and_motors() 67 | 68 | print("Rotate right motor") 69 | time.sleep(0.5) 70 | motor_drive("0", SPEED) 71 | print_counter(2.0) 72 | reset_counters_and_motors() 73 | 74 | print("Move forward") 75 | time.sleep(0.5) 76 | motor_drive(SPEED, SPEED) 77 | print_counter(2.0) 78 | reset_counters_and_motors() 79 | 80 | print("Move backward") 81 | time.sleep(0.5) 82 | motor_drive("-"+SPEED, "-"+SPEED) 83 | print_counter(2.0) 84 | reset_counters_and_motors() 85 | 86 | print("Motor Off") 87 | with open(filename_motoren, 'w') as f: 88 | f.write("0") 89 | -------------------------------------------------------------------------------- /SampleProgram/step6.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2020 RT Corporation 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | MOTOR_EN=/dev/rtmotoren0 18 | MOTOR_R=/dev/rtmotor_raw_r0 19 | MOTOR_L=/dev/rtmotor_raw_l0 20 | COUNTER_R=/dev/rtcounter_r0 21 | COUNTER_L=/dev/rtcounter_l0 22 | 23 | SPEED=400 24 | 25 | function echo_counter () { 26 | SECONDS=0 27 | while [ $SECONDS -lt "$1" ] 28 | do 29 | echo "count_l:$(cat $COUNTER_L), count_r:$(cat $COUNTER_R)" 30 | done 31 | } 32 | 33 | function reset_counters_and_motors () { 34 | echo 0 | tee $MOTOR_L $MOTOR_R > /dev/null 35 | echo "Reset counter" 36 | echo 0 | tee $COUNTER_L $COUNTER_R > /dev/null 37 | echo "count_l:$(cat $COUNTER_L), count_r:$(cat $COUNTER_R)" 38 | } 39 | 40 | reset_counters_and_motors 41 | 42 | echo "Motor On" 43 | echo 1 > $MOTOR_EN 44 | 45 | echo "Rotate left motor" 46 | sleep 0.5 47 | echo $SPEED > $MOTOR_L 48 | echo_counter 2 49 | reset_counters_and_motors 50 | 51 | echo "Rotate right motor" 52 | sleep 0.5 53 | echo $SPEED > $MOTOR_R 54 | echo_counter 2 55 | reset_counters_and_motors 56 | 57 | echo "Move forward" 58 | sleep 0.5 59 | echo $SPEED | tee $MOTOR_L $MOTOR_R > /dev/null 60 | echo_counter 2 61 | reset_counters_and_motors 62 | 63 | echo "Move backward" 64 | sleep 0.5 65 | echo -$SPEED | tee $MOTOR_L $MOTOR_R > /dev/null 66 | echo_counter 2 67 | reset_counters_and_motors 68 | 69 | echo "Motor Off" 70 | echo 0 > $MOTOR_EN 71 | -------------------------------------------------------------------------------- /cad_data/README.md: -------------------------------------------------------------------------------- 1 | This directory has been moved to [rt-net/RaspberryPiMouse_Hardware](https://github.com/rt-net/RaspberryPiMouse_Hardware). 2 | 3 | このディレクトリは[rt-net/RaspberryPiMouse_Hardware](https://github.com/rt-net/RaspberryPiMouse_Hardware)へ移行しました。 4 | -------------------------------------------------------------------------------- /lib/Pi1B+/3.18.14+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/3.18.14+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.0.5+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.0.5+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.0.6+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.0.6+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.0.7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.0.7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.0.8+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.0.8+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.0.9+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.0.9+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.10+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.10+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.13+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.13+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.15+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.15+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.5+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.5+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.6+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.6+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.8+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.8+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi1B+/4.1.9+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi1B+/4.1.9+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/3.18.0-20-rpi2/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/3.18.0-20-rpi2/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/3.18.9-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/3.18.9-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.0.5-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.0.5-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.0.6-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.0.6-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.0.7-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.0.7-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.0.8-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.0.8-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.0.9-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.0.9-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.10-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.10-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.13-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.13-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.15-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.15-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.17-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.17-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.19-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.19-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.21-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.21-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.5-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.5-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.6-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.6-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.7-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.7-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.8-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.8-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.1.9-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.1.9-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.14.50-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.14.50-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.14.69-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.14.69-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.14.70-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.14.70-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.14.98-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.14.98-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.19.42-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.19.42-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.19.75-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.19.75-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.19.97-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.19.97-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.0-1009-raspi2/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.0-1009-raspi2/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.10-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.10-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.13-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.13-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.14-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.14-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.21-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.21-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.34-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.34-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.35-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.35-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.39-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.39-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.41-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.41-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.50-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.50-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.4.9-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.4.9-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.9.35-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.9.35-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.9.51-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.9.51-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.9.70-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.9.70-v7+/rtmouse.ko -------------------------------------------------------------------------------- /lib/Pi2B+/4.9.80-v7+/rtmouse.ko: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rt-net/RaspberryPiMouse/484796ea3441b17fc403ec332819c79fda2d7764/lib/Pi2B+/4.9.80-v7+/rtmouse.ko -------------------------------------------------------------------------------- /src/drivers/.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | IndentWidth: 8 3 | UseTab: Always 4 | BreakBeforeBraces: Linux 5 | AllowShortIfStatementsOnASingleLine: false 6 | IndentCaseLabels: false 7 | -------------------------------------------------------------------------------- /src/drivers/Makefile: -------------------------------------------------------------------------------- 1 | Makefile.header_from_apt -------------------------------------------------------------------------------- /src/drivers/Makefile.header_from_apt: -------------------------------------------------------------------------------- 1 | MODULE:= rtmouse 2 | obj-m:= $(MODULE).o 3 | $(MODULE)-y:= $(MODULE)_main.o $(MODULE)_dev.o $(MODULE)_spi.o $(MODULE)_i2c.o $(MODULE)_gpio.o 4 | clean-files:= *.o *.ko *.mod.[co] *~ 5 | 6 | LINUX_SRC_DIR:=/usr/src/linux-headers-$(shell uname -r) 7 | VERBOSE:=0 8 | 9 | $(MODULE).ko: $(MODULE)_main.c $(MODULE)_dev.c $(MODULE)_spi.c $(MODULE)_i2c.c $(MODULE)_gpio.c $(MODULE).h 10 | make -C $(LINUX_SRC_DIR) M=$(shell pwd) V=$(VERBOSE) modules 11 | 12 | clean: 13 | make -C $(LINUX_SRC_DIR) M=$(shell pwd) V=$(VERBOSE) clean 14 | 15 | install: $(MODULE).ko 16 | cp ../../50-rtmouse.rules /etc/udev/rules.d/ 17 | 18 | uninstall: 19 | rm /etc/udev/rules.d/50-rtmouse.rules 20 | 21 | #Reference: http://www.devdrv.co.jp/linux/kernel26-makefile.htm 22 | -------------------------------------------------------------------------------- /src/drivers/Makefile.header_from_source: -------------------------------------------------------------------------------- 1 | MODULE:= rtmouse 2 | obj-m:= $(MODULE).o 3 | $(MODULE)-y:= $(MODULE)_main.o $(MODULE)_dev.o $(MODULE)_spi.o $(MODULE)_i2c.o $(MODULE)_gpio.o 4 | clean-files:= *.o *.ko *.mod.[co] *~ 5 | 6 | LINUX_SRC_DIR:=/usr/src/linux 7 | VERBOSE:=0 8 | 9 | $(MODULE).ko: $(MODULE)_main.c $(MODULE)_dev.c $(MODULE)_spi.c $(MODULE)_i2c.c $(MODULE)_gpio.c $(MODULE).h 10 | make -C $(LINUX_SRC_DIR) M=$(shell pwd) V=$(VERBOSE) modules 11 | 12 | clean: 13 | make -C $(LINUX_SRC_DIR) M=$(shell pwd) V=$(VERBOSE) clean 14 | -------------------------------------------------------------------------------- /src/drivers/rtmouse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse.h 4 | * Raspberry Pi Mouse device driver header 5 | * 6 | * Copyright (C) 2024 RT Corporation 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; version 2. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | * MA 02110-1301, USA. 21 | */ 22 | 23 | #ifndef RTMOUSE_H 24 | #define RTMOUSE_H 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | // define the Raspberry Pi version here 51 | // Raspberry Pi 1 B/A/B+/A+: 1 52 | // Raspberry Pi 2 B : 2 53 | // Raspberry Pi 3 B/A+/B+ : 2 54 | // Raspberry Pi 4 B : 4 55 | #define RASPBERRYPI 2 56 | 57 | #define DEV_RIGHT 0 58 | #define DEV_LEFT 1 59 | 60 | /* --- Device ID --- */ 61 | #define ID_DEV_LED 0 62 | #define ID_DEV_SWITCH 1 63 | #define ID_DEV_SENSOR 2 64 | #define ID_DEV_BUZZER 3 65 | #define ID_DEV_MOTORRAWR 4 66 | #define ID_DEV_MOTORRAWL 5 67 | #define ID_DEV_MOTOREN 6 68 | #define ID_DEV_MOTOR 7 69 | #define ID_DEV_CNT 8 70 | #define ID_DEV_SIZE 9 71 | 72 | #define NUM_DEV_TOTAL \ 73 | (NUM_DEV[ID_DEV_LED] + NUM_DEV[ID_DEV_SWITCH] + \ 74 | NUM_DEV[ID_DEV_SENSOR] + NUM_DEV[ID_DEV_BUZZER] + \ 75 | NUM_DEV[ID_DEV_MOTORRAWR] + NUM_DEV[ID_DEV_MOTORRAWL] + \ 76 | NUM_DEV[ID_DEV_MOTOREN] + NUM_DEV[ID_DEV_MOTOR]) 77 | 78 | #define DEVNAME_SENSOR "rtlightsensor" 79 | #define DEVNAME_CNTR "rtcounter_r" 80 | #define DEVNAME_CNTL "rtcounter_l" 81 | #define DRIVER_NAME "rtmouse" 82 | 83 | /* SPI */ 84 | #define SPI_BUS_NUM 0 85 | #define SPI_CHIP_SELECT 0 86 | 87 | /* --- Device Major and Minor Numbers --- */ 88 | #define DEV_MAJOR 0 89 | #define DEV_MINOR 0 90 | 91 | /* --- GPIO Pin Definitions --- */ 92 | #define R_AD_CH 3 93 | #define L_AD_CH 0 94 | #define RF_AD_CH 2 95 | #define LF_AD_CH 1 96 | 97 | #define R_LED_BASE 22 98 | #define L_LED_BASE 4 99 | #define RF_LED_BASE 27 100 | #define LF_LED_BASE 17 101 | 102 | #define LED0_BASE 25 103 | #define LED1_BASE 24 104 | #define LED2_BASE 23 105 | #define LED3_BASE 18 106 | 107 | #define SW1_PIN 20 108 | #define SW2_PIN 26 109 | #define SW3_PIN 21 110 | 111 | #define BUZZER_BASE 19 112 | 113 | #define MOTCLK_L_BASE 12 114 | #define MOTDIR_L_BASE 16 115 | 116 | #define MOTCLK_R_BASE 13 117 | #define MOTDIR_R_BASE 6 118 | 119 | #define MOTEN_BASE 5 120 | 121 | #define PWM_ORG0_BASE 40 122 | #define PWM_ORG1_BASE 45 123 | 124 | /* --- Register Address --- */ 125 | /* Base Addr */ 126 | #if RASPBERRYPI == 1 127 | #define RPI_REG_BASE 0x20000000 128 | #elif RASPBERRYPI == 2 129 | #define RPI_REG_BASE 0x3f000000 130 | #elif RASPBERRYPI == 4 131 | #define RPI_REG_BASE 0xfe000000 132 | /* 2711 has a different mechanism for pin pull-up/down/enable */ 133 | #define GPPUPPDN0 57 /* Pin pull-up/down for pins 15:0 */ 134 | #define GPPUPPDN1 58 /* Pin pull-up/down for pins 31:16 */ 135 | #define GPPUPPDN2 59 /* Pin pull-up/down for pins 47:32 */ 136 | #define GPPUPPDN3 60 /* Pin pull-up/down for pins 57:48 */ 137 | #endif 138 | 139 | /* GPIO Addr */ 140 | #define RPI_GPIO_OFFSET 0x200000 141 | #define RPI_GPIO_SIZE 0xC0 142 | #define RPI_GPIO_BASE (RPI_REG_BASE + RPI_GPIO_OFFSET) 143 | #define REG_GPIO_NAME "RPi mouse GPIO" 144 | 145 | /* Pwm Addr */ 146 | #define RPI_PWM_OFFSET 0x20C000 147 | #define RPI_PWM_SIZE 0xC0 148 | #define RPI_PWM_BASE (RPI_REG_BASE + RPI_PWM_OFFSET) 149 | #define REG_PWM_NAME "RPi mouse PWM" 150 | 151 | /* Clock Addr */ 152 | #define RPI_CLK_OFFSET 0x101000 153 | #define RPI_CLK_SIZE 0x100 154 | #define RPI_CLK_BASE (RPI_REG_BASE + RPI_CLK_OFFSET) 155 | #define REG_CLK_NAME "RPi mouse CLK" 156 | 157 | /* --- General Options --- */ 158 | /* Clock Offset */ 159 | #define CLK_PWM_INDEX 0xa0 160 | #define CLK_PWMDIV_INDEX 0xa4 161 | 162 | /* GPIO PUPD select */ 163 | #if RASPBERRYPI == 4 164 | #define GPIO_PULLNONE 0x0 165 | #define GPIO_PULLUP 0x1 166 | #define GPIO_PULLDOWN 0x2 167 | #else 168 | #define GPIO_PULLNONE 0x0 169 | #define GPIO_PULLDOWN 0x1 170 | #define GPIO_PULLUP 0x2 171 | #endif 172 | 173 | /* GPIO Function */ 174 | #define RPI_GPF_INPUT 0x00 175 | #define RPI_GPF_OUTPUT 0x01 176 | #define RPI_GPF_ALT0 0x04 177 | #define RPI_GPF_ALT5 0x02 178 | 179 | /* GPIO Register Index */ 180 | #define RPI_GPFSEL0_INDEX 0 181 | #define RPI_GPFSEL1_INDEX 1 182 | #define RPI_GPFSEL2_INDEX 2 183 | #define RPI_GPFSEL3_INDEX 3 184 | 185 | #define RPI_GPSET0_INDEX 7 186 | #define RPI_GPCLR0_INDEX 10 187 | 188 | /* GPIO Mask */ 189 | #define RPI_GPIO_P1MASK \ 190 | (uint32_t)((0x01 << 2) | (0x01 << 3) | (0x01 << 4) | (0x01 << 7) | \ 191 | (0x01 << 8) | (0x01 << 9) | (0x01 << 10) | (0x01 << 11) | \ 192 | (0x01 << 14) | (0x01 << 15) | (0x01 << 17) | (0x01 << 18) | \ 193 | (0x01 << 22) | (0x01 << 23) | (0x01 << 24) | (0x01 << 25) | \ 194 | (0x01 << 27)) 195 | #define RPI_GPIO_P2MASK (uint32_t)0xffffffff 196 | 197 | /* PWM Index */ 198 | #define RPI_PWM_CTRL 0x0 199 | #define RPI_PWM_STA 0x4 200 | #define RPI_PWM_DMAC 0x8 201 | #define RPI_PWM_RNG1 0x10 202 | #define RPI_PWM_DAT1 0x14 203 | #define RPI_PWM_FIF1 0x18 204 | #define RPI_PWM_RNG2 0x20 205 | #define RPI_PWM_DAT2 0x24 206 | 207 | #if RASPBERRYPI == 4 208 | #define PWM_BASECLK 27000000 209 | #else 210 | #define PWM_BASECLK 9600000 211 | #endif 212 | 213 | /* A/D Parameter */ 214 | #define MCP320X_PACKET_SIZE 3 215 | #define MCP320X_DIFF 0 216 | #define MCP320X_SINGLE 1 217 | #define MCP3204_CHANNELS 4 218 | 219 | /* I2C Parameter */ 220 | #define DEV_ADDR_CNTL 0x10 221 | #define DEV_ADDR_CNTR 0x11 222 | #define CNT_ADDR_MSB 0x10 223 | #define CNT_ADDR_LSB 0x11 224 | 225 | /* Motor Parameter */ 226 | #define MOTOR_UNCONTROLLABLE_FREQ 5 227 | 228 | /* I2C */ 229 | #define SIGNED_COUNT_SIZE 32767 230 | #define MAX_PULSE_COUNT 65535 231 | 232 | /* --- Buffer --- */ 233 | #define MAX_BUFLEN 64 234 | 235 | /* --- Variable Type definitions --- */ 236 | /* SPI */ 237 | struct mcp3204_drvdata { 238 | struct spi_device *spi; 239 | struct mutex lock; 240 | unsigned char tx[MCP320X_PACKET_SIZE] ____cacheline_aligned; 241 | unsigned char rx[MCP320X_PACKET_SIZE] ____cacheline_aligned; 242 | struct spi_transfer xfer ____cacheline_aligned; 243 | struct spi_message msg ____cacheline_aligned; 244 | }; 245 | 246 | /* I2C */ 247 | struct rtcnt_device_info { 248 | struct cdev cdev; 249 | unsigned int device_major; 250 | unsigned int device_minor; 251 | struct class *device_class; 252 | struct i2c_client *client; 253 | struct mutex lock; 254 | int signed_pulse_count; 255 | int raw_pulse_count; 256 | }; 257 | 258 | /* --- used in rtmouse_dev.c --- */ 259 | extern const char *NAME_DEV[ID_DEV_SIZE]; 260 | extern int _major_dev[ID_DEV_SIZE]; 261 | extern int _minor_dev[ID_DEV_SIZE]; 262 | extern struct class *class_dev[ID_DEV_SIZE]; 263 | extern volatile void __iomem *pwm_base; 264 | extern volatile uint32_t *gpio_base; 265 | extern struct mutex lock; 266 | extern struct spi_board_info mcp3204_info; 267 | extern struct file_operations dev_fops[ID_DEV_SIZE]; 268 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 269 | extern struct device *mcp320x_dev; 270 | #endif 271 | int buzzer_init(void); 272 | int register_dev(int id_dev); 273 | 274 | /* --- used in rtmouse_spi.c --- */ 275 | int mcp3204_init(void); 276 | void mcp3204_exit(void); 277 | 278 | /* --- used in rtmouse_i2c.c --- */ 279 | extern const unsigned int NUM_DEV[ID_DEV_SIZE]; 280 | extern struct cdev *cdev_array; 281 | extern volatile int cdev_index; 282 | int i2c_counter_init(void); 283 | void i2c_counter_exit(void); 284 | 285 | /* --- used in rtmouse_gpio.c --- */ 286 | int rpi_gpio_function_set(int pin, uint32_t func); 287 | void rpi_gpio_set32(uint32_t mask, uint32_t val); 288 | void rpi_gpio_clear32(uint32_t mask, uint32_t val); 289 | void rpi_pwm_write32(uint32_t offset, uint32_t val); 290 | int gpio_map(void); 291 | int gpio_unmap(void); 292 | 293 | #endif // RTMOUSE_H 294 | -------------------------------------------------------------------------------- /src/drivers/rtmouse_dev.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse_dev.c 4 | * Define device file operations and register device 5 | * 6 | * Copyright (C) 2024 RT Corporation 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; version 2. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | * MA 02110-1301, USA. 21 | */ 22 | 23 | #include "rtmouse.h" 24 | 25 | static unsigned int motor_l_freq_is_positive = 1; 26 | static unsigned int motor_r_freq_is_positive = 1; 27 | 28 | /* 29 | * --- Device Names(+%u) --- 30 | * used in register_dev() 31 | */ 32 | static const char *NAME_DEV_U[ID_DEV_SIZE] = { 33 | [ID_DEV_LED] = "rtled%u", 34 | [ID_DEV_SWITCH] = "rtswitch%u", 35 | [ID_DEV_SENSOR] = "rtlightsensor%u", 36 | [ID_DEV_BUZZER] = "rtbuzzer%u", 37 | [ID_DEV_MOTORRAWR] = "rtmotor_raw_r%u", 38 | [ID_DEV_MOTORRAWL] = "rtmotor_raw_l%u", 39 | [ID_DEV_MOTOREN] = "rtmotoren%u", 40 | [ID_DEV_MOTOR] = "rtmotor%u"}; 41 | 42 | /* 43 | * i2c_counter_set - set value to I2C pulse counter 44 | * called by rtcnt_write() 45 | */ 46 | static int i2c_counter_set(struct rtcnt_device_info *dev_info, int setval) 47 | { 48 | int ret = 0; 49 | int lsb = 0, msb = 0; 50 | struct i2c_client *client = dev_info->client; 51 | 52 | // printk(KERN_INFO "set 0x%x = 0x%x\n", client->addr, setval); 53 | msb = (setval >> 8) & 0xFF; 54 | lsb = setval & 0xFF; 55 | mutex_lock(&dev_info->lock); 56 | // printk(KERN_INFO "set 0x%x msb = 0x%x\n", client->addr, msb); 57 | ret = i2c_smbus_write_byte_data(client, 0x10, msb); 58 | if (ret < 0) { 59 | printk(KERN_ERR 60 | "%s: Failed writing to i2c counter device, addr=0x%x\n", 61 | __func__, client->addr); 62 | mutex_unlock(&dev_info->lock); 63 | return -ENODEV; 64 | } 65 | // printk(KERN_INFO "set 0x%x lsb = 0x%x\n", client->addr, lsb); 66 | ret = i2c_smbus_write_byte_data(client, 0x11, lsb); 67 | if (ret < 0) { 68 | printk(KERN_ERR 69 | "%s: Failed writing to i2c counter device, addr=0x%x\n", 70 | __func__, client->addr); 71 | mutex_unlock(&dev_info->lock); 72 | return -ENODEV; 73 | } 74 | mutex_unlock(&dev_info->lock); 75 | return ret; 76 | } 77 | 78 | /* 79 | * i2c_counter_read - get value from I2C pulse counter 80 | * called by rtcnt_read() 81 | */ 82 | static int i2c_counter_read(struct rtcnt_device_info *dev_info, int *ret) 83 | { 84 | int lsb = 0, msb = 0; 85 | // printk(KERN_INFO "read 0x%x\n", client->addr); 86 | struct i2c_client *client = dev_info->client; 87 | mutex_lock(&dev_info->lock); 88 | 89 | lsb = i2c_smbus_read_byte_data(client, CNT_ADDR_LSB); 90 | if (lsb < 0) { 91 | printk( 92 | KERN_ERR 93 | "%s: Failed reading from i2c counter device, addr=0x%x\n", 94 | __func__, client->addr); 95 | mutex_unlock(&dev_info->lock); 96 | return -ENODEV; 97 | } 98 | msb = i2c_smbus_read_byte_data(client, CNT_ADDR_MSB); 99 | if (msb < 0) { 100 | printk( 101 | KERN_ERR 102 | "%s: Failed reading from i2c counter device, addr=0x%x\n", 103 | __func__, client->addr); 104 | mutex_unlock(&dev_info->lock); 105 | return -ENODEV; 106 | } 107 | mutex_unlock(&dev_info->lock); 108 | 109 | *ret = ((msb << 8) & 0xFF00) + (lsb & 0xFF); 110 | 111 | // printk(KERN_INFO "0x%x == 0x%x\n", client->addr, *ret); 112 | return 0; 113 | } 114 | 115 | /* 116 | * update_signed_count - update signed pulse count of dev_info 117 | * called by rtcnt_read() 118 | */ 119 | static void update_signed_count(struct rtcnt_device_info *dev_info, 120 | int rtcnt_count) 121 | { 122 | int diff_count = rtcnt_count - dev_info->raw_pulse_count; 123 | 124 | // カウントがMAX_PULSE_COUNTから0に変わる場合の処理 125 | // ただし、それ以外でもdiffが負の値になることがある 126 | // そのため、diffが十分に大きな負の値の場合に処理する 127 | // if(diff_count < 0) では正常に動作しない 128 | if (diff_count < -SIGNED_COUNT_SIZE) { 129 | diff_count += MAX_PULSE_COUNT; 130 | } 131 | 132 | if (dev_info->client->addr == DEV_ADDR_CNTL) { 133 | if (motor_l_freq_is_positive) { 134 | dev_info->signed_pulse_count += diff_count; 135 | } else { 136 | dev_info->signed_pulse_count -= diff_count; 137 | } 138 | } else { 139 | if (motor_r_freq_is_positive) { 140 | dev_info->signed_pulse_count += diff_count; 141 | } else { 142 | dev_info->signed_pulse_count -= diff_count; 143 | } 144 | } 145 | 146 | if (dev_info->signed_pulse_count > SIGNED_COUNT_SIZE || 147 | dev_info->signed_pulse_count < -SIGNED_COUNT_SIZE) { 148 | dev_info->signed_pulse_count = 0; 149 | } 150 | } 151 | 152 | /* 153 | * reset_signed_count - reset signed pulse count of dev_info 154 | * called by rtcnt_write() 155 | */ 156 | static void reset_signed_count(struct rtcnt_device_info *dev_info, 157 | int rtcnt_count) 158 | { 159 | int raw_count; 160 | 161 | if (rtcnt_count > SIGNED_COUNT_SIZE) { 162 | rtcnt_count = SIGNED_COUNT_SIZE; 163 | } else if (rtcnt_count < -SIGNED_COUNT_SIZE) { 164 | rtcnt_count = -SIGNED_COUNT_SIZE; 165 | } 166 | dev_info->signed_pulse_count = rtcnt_count; 167 | i2c_counter_read(dev_info, &raw_count); 168 | dev_info->raw_pulse_count = raw_count; 169 | } 170 | 171 | /* 172 | * mcp3204_get_value - get sensor data from MCP3204 173 | * called by sensor_read() 174 | */ 175 | static unsigned int mcp3204_get_value(int channel) 176 | { 177 | struct device *dev; 178 | struct mcp3204_drvdata *data; 179 | struct spi_device *spi; 180 | char str[128]; 181 | 182 | unsigned int r = 0; 183 | unsigned char c = channel & 0x03; 184 | 185 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 186 | 187 | if (mcp320x_dev == NULL) 188 | return 0; 189 | dev = mcp320x_dev; 190 | 191 | #else 192 | struct spi_master *master; 193 | master = spi_busnum_to_master(mcp3204_info.bus_num); 194 | snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), 195 | mcp3204_info.chip_select); 196 | dev = bus_find_device_by_name(&spi_bus_type, NULL, str); 197 | #endif 198 | 199 | spi = to_spi_device(dev); 200 | data = (struct mcp3204_drvdata *)spi_get_drvdata(spi); 201 | mutex_lock(&data->lock); 202 | data->tx[0] = 1 << 2; // start bit 203 | data->tx[0] |= 1 << 1; // Single 204 | data->tx[1] = c << 6; // channel 205 | data->tx[2] = 0; 206 | 207 | if (spi_sync(data->spi, &data->msg)) { 208 | printk(KERN_INFO "%s: spi_sync_transfer returned non zero\n", 209 | __func__); 210 | } 211 | 212 | mutex_unlock(&data->lock); 213 | 214 | r = (data->rx[1] & 0xf) << 8; 215 | r |= data->rx[2]; 216 | 217 | // printk(KERN_INFO "%s: get result on ch[%d] : %04d\n", __func__, 218 | // channel, r); 219 | 220 | return r; 221 | } 222 | 223 | /* --- GPIO Operation --- */ 224 | /* getPWMCount function for GPIO Operation */ 225 | static int getPWMCount(int freq) 226 | { 227 | if (freq < 1) 228 | return PWM_BASECLK; 229 | if (freq > 10000) 230 | return PWM_BASECLK / 10000; 231 | 232 | return PWM_BASECLK / freq; 233 | } 234 | 235 | /* 236 | * motor function 237 | * called by parseMotorCmd() and rawmotor_l_write() 238 | */ 239 | static void set_motor_freq(int freq, const int dev_side) 240 | { 241 | int dat; 242 | 243 | rpi_gpio_function_set(BUZZER_BASE, RPI_GPF_OUTPUT); 244 | 245 | // Reset uncontrollable frequency to zero. 246 | if (abs(freq) < MOTOR_UNCONTROLLABLE_FREQ) { 247 | freq = 0; 248 | } 249 | 250 | if (freq == 0) { 251 | if (dev_side == DEV_LEFT) { 252 | rpi_gpio_function_set(MOTCLK_L_BASE, RPI_GPF_OUTPUT); 253 | } else if (dev_side == DEV_RIGHT) { 254 | rpi_gpio_function_set(MOTCLK_R_BASE, RPI_GPF_OUTPUT); 255 | } 256 | return; 257 | } else { 258 | if (dev_side == DEV_LEFT) { 259 | rpi_gpio_function_set(MOTCLK_L_BASE, RPI_GPF_ALT0); 260 | } else if (dev_side == DEV_RIGHT) { 261 | rpi_gpio_function_set(MOTCLK_R_BASE, RPI_GPF_ALT0); 262 | } 263 | } 264 | 265 | if (freq > 0) { 266 | if (dev_side == DEV_LEFT) { 267 | motor_l_freq_is_positive = 1; 268 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << MOTDIR_L_BASE); 269 | } else if (dev_side == DEV_RIGHT) { 270 | motor_r_freq_is_positive = 1; 271 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << MOTDIR_R_BASE); 272 | } 273 | } else { 274 | if (dev_side == DEV_LEFT) { 275 | motor_l_freq_is_positive = 0; 276 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << MOTDIR_L_BASE); 277 | freq = -freq; 278 | } else if (dev_side == DEV_RIGHT) { 279 | motor_r_freq_is_positive = 0; 280 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << MOTDIR_R_BASE); 281 | freq = -freq; 282 | } 283 | } 284 | 285 | dat = getPWMCount(freq); 286 | 287 | if (dev_side == DEV_LEFT) { 288 | rpi_pwm_write32(RPI_PWM_RNG1, dat); 289 | rpi_pwm_write32(RPI_PWM_DAT1, dat >> 1); 290 | } else if (dev_side == DEV_RIGHT) { 291 | rpi_pwm_write32(RPI_PWM_RNG2, dat); 292 | rpi_pwm_write32(RPI_PWM_DAT2, dat >> 1); 293 | } 294 | 295 | return; 296 | } 297 | 298 | /* 299 | * Parse motor command 300 | * called by motor_write() 301 | */ 302 | static int parseMotorCmd(const char __user *buf, size_t count, int *ret) 303 | { 304 | int r_motor_val, l_motor_val, time_val; 305 | char *newbuf = kmalloc(sizeof(char) * count, GFP_KERNEL); 306 | 307 | if (copy_from_user(newbuf, buf, sizeof(char) * count)) { 308 | kfree(newbuf); 309 | return -EFAULT; 310 | } 311 | 312 | sscanf(newbuf, "%d%d%d\n", &l_motor_val, &r_motor_val, &time_val); 313 | 314 | kfree(newbuf); 315 | 316 | mutex_lock(&lock); 317 | 318 | set_motor_freq(l_motor_val, DEV_LEFT); 319 | set_motor_freq(r_motor_val, DEV_RIGHT); 320 | 321 | msleep_interruptible(time_val); 322 | 323 | set_motor_freq(0, DEV_LEFT); 324 | set_motor_freq(0, DEV_RIGHT); 325 | 326 | mutex_unlock(&lock); 327 | 328 | return count; 329 | } 330 | 331 | /* 332 | * Turn On LEDs 333 | * return 0 : device close 334 | * called by led_write() 335 | */ 336 | static int led_put(int ledno) 337 | { 338 | switch (ledno) { 339 | case 0: 340 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LED0_BASE); 341 | break; 342 | case 1: 343 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LED1_BASE); 344 | break; 345 | case 2: 346 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LED2_BASE); 347 | break; 348 | case 3: 349 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LED3_BASE); 350 | break; 351 | } 352 | return 0; 353 | } 354 | 355 | /* 356 | * Turn Off LEDs 357 | * return 0 : device close 358 | * called by led_write() 359 | */ 360 | static int led_del(int ledno) 361 | { 362 | switch (ledno) { 363 | case 0: 364 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LED0_BASE); 365 | break; 366 | case 1: 367 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LED1_BASE); 368 | break; 369 | case 2: 370 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LED2_BASE); 371 | break; 372 | case 3: 373 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LED3_BASE); 374 | break; 375 | } 376 | 377 | return 0; 378 | } 379 | 380 | /* 381 | * rtcnt_read - Read value from right/left pulse counter 382 | * Read function of /dev/rtcounter_* 383 | */ 384 | static ssize_t rtcnt_read(struct file *filep, char __user *buf, size_t count, 385 | loff_t *f_pos) 386 | { 387 | struct rtcnt_device_info *dev_info = filep->private_data; 388 | 389 | unsigned char rw_buf[64]; 390 | int buflen; 391 | 392 | int rtcnt_count = 0; 393 | if (*f_pos > 0) 394 | return 0; /* close device */ 395 | i2c_counter_read(dev_info, &rtcnt_count); 396 | 397 | if (dev_info->device_minor == 1) { 398 | update_signed_count(dev_info, rtcnt_count); 399 | dev_info->raw_pulse_count = rtcnt_count; 400 | rtcnt_count = dev_info->signed_pulse_count; 401 | } else { 402 | dev_info->raw_pulse_count = rtcnt_count; 403 | } 404 | 405 | /* set sensor data to rw_buf(static buffer) */ 406 | sprintf(rw_buf, "%d\n", rtcnt_count); 407 | buflen = strlen(rw_buf); 408 | count = buflen; 409 | 410 | /* copy data to user area */ 411 | if (copy_to_user((void *)buf, &rw_buf, count)) { 412 | printk(KERN_INFO "err read buffer from %s\n", rw_buf); 413 | printk(KERN_INFO "err sample_char_read size(%zu)\n", count); 414 | printk(KERN_INFO "sample_char_read size err(%d)\n", -EFAULT); 415 | return -EFAULT; 416 | } 417 | *f_pos += count; 418 | return count; 419 | } 420 | 421 | /* 422 | * cnt_write - Set value to right/left pulse counter 423 | * Write function of /dev/rtcounter 424 | */ 425 | static ssize_t rtcnt_write(struct file *filep, const char __user *buf, 426 | size_t count, loff_t *pos) 427 | { 428 | struct rtcnt_device_info *dev_info = filep->private_data; 429 | 430 | int rtcnt_count = 0; 431 | int ret; 432 | 433 | ret = kstrtoint_from_user(buf, count, 10, &rtcnt_count); 434 | if (ret) { 435 | printk(KERN_ERR "%s: error parsing string to int in %s()\n", 436 | DRIVER_NAME, __func__); 437 | return ret; 438 | } 439 | 440 | i2c_counter_set(dev_info, rtcnt_count); 441 | 442 | if (dev_info->device_minor == 1) { 443 | reset_signed_count(dev_info, rtcnt_count); 444 | } 445 | 446 | printk(KERN_INFO "%s: set pulse counter value %d\n", DRIVER_NAME, 447 | rtcnt_count); 448 | return count; 449 | } 450 | 451 | /* 452 | * Read Push Switches 453 | * return 0 : device close 454 | */ 455 | static ssize_t sw_read(struct file *filep, char __user *buf, size_t count, 456 | loff_t *f_pos) 457 | { 458 | int buflen = 0; 459 | unsigned char rw_buf[MAX_BUFLEN]; 460 | unsigned int ret = 0; 461 | int len; 462 | int index; 463 | unsigned int pin = SW1_PIN; 464 | uint32_t mask; 465 | int minor = *((int *)filep->private_data); 466 | #if RASPBERRYPI == 4 467 | int pullreg = GPPUPPDN1 + (pin >> 4); // SW1, 2, 3 is between GPIO16-31 468 | int pullshift = (pin & 0xf) << 1; 469 | unsigned int pullbits; 470 | unsigned int pull; 471 | #endif 472 | 473 | switch (minor) { 474 | case 0: 475 | pin = SW1_PIN; 476 | break; 477 | case 1: 478 | pin = SW2_PIN; 479 | break; 480 | case 2: 481 | pin = SW3_PIN; 482 | break; 483 | default: 484 | return 0; 485 | break; 486 | } 487 | 488 | if (*f_pos > 0) 489 | return 0; /* End of file */ 490 | 491 | #if RASPBERRYPI == 4 492 | pull = GPIO_PULLUP; 493 | pullbits = *(gpio_base + pullreg); 494 | pullbits &= ~(3 << pullshift); 495 | pullbits |= (pull << pullshift); 496 | *(gpio_base + pullreg) = pullbits; 497 | #else 498 | // プルモード (2bit)を書き込む NONE/DOWN/UP 499 | gpio_base[37] = GPIO_PULLUP & 0x3; // GPPUD 500 | // ピンにクロックを供給(前後にウェイト) 501 | msleep(1); 502 | gpio_base[38] = 0x1 << pin; // GPPUDCLK0 503 | msleep(1); 504 | // プルモード・クロック状態をクリアして終了 505 | gpio_base[37] = 0; 506 | gpio_base[38] = 0; 507 | #endif 508 | 509 | index = RPI_GPFSEL0_INDEX + pin / 10; 510 | mask = ~(0x7 << ((pin % 10) * 3)); 511 | 512 | ret = ((gpio_base[13] & (0x01 << pin)) != 0); 513 | sprintf(rw_buf, "%d\n", ret); 514 | 515 | buflen = strlen(rw_buf); 516 | count = buflen; 517 | len = buflen; 518 | 519 | if (copy_to_user((void *)buf, &rw_buf, count)) { 520 | printk(KERN_INFO "err read buffer from ret %d\n", ret); 521 | printk(KERN_INFO "err read buffer from %s\n", rw_buf); 522 | printk(KERN_INFO "err sample_char_read size(%zu)\n", count); 523 | printk(KERN_INFO "sample_char_read size err(%d)\n", -EFAULT); 524 | return 0; 525 | } 526 | *f_pos += count; 527 | 528 | return count; 529 | } 530 | 531 | /* 532 | * Read Sensor information 533 | * return 0 : device close 534 | */ 535 | static ssize_t sensor_read(struct file *filep, char __user *buf, size_t count, 536 | loff_t *f_pos) 537 | { 538 | int buflen = 0; 539 | unsigned char rw_buf[MAX_BUFLEN]; 540 | unsigned int ret = 0; 541 | int len; 542 | 543 | // printk(KERN_INFO "new\n"); 544 | 545 | int usecs = 30; 546 | int rf = 0, lf = 0, r = 0, l = 0; 547 | int orf = 0, olf = 0, or = 0, ol = 0; 548 | 549 | if (*f_pos > 0) 550 | return 0; /* End of file */ 551 | 552 | /* get values through MCP3204 */ 553 | /* Right side */ 554 | or = mcp3204_get_value(R_AD_CH); 555 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << R_LED_BASE); 556 | udelay(usecs); 557 | r = mcp3204_get_value(R_AD_CH); 558 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << R_LED_BASE); 559 | udelay(usecs); 560 | /* Left side */ 561 | ol = mcp3204_get_value(L_AD_CH); 562 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << L_LED_BASE); 563 | udelay(usecs); 564 | l = mcp3204_get_value(L_AD_CH); 565 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << L_LED_BASE); 566 | udelay(usecs); 567 | /* Right front side */ 568 | orf = mcp3204_get_value(RF_AD_CH); 569 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << RF_LED_BASE); 570 | udelay(usecs); 571 | rf = mcp3204_get_value(RF_AD_CH); 572 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << RF_LED_BASE); 573 | udelay(usecs); 574 | /* Left front side */ 575 | olf = mcp3204_get_value(LF_AD_CH); 576 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LF_LED_BASE); 577 | udelay(usecs); 578 | lf = mcp3204_get_value(LF_AD_CH); 579 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LF_LED_BASE); 580 | udelay(usecs); 581 | 582 | /* set sensor data to rw_buf(static buffer) */ 583 | snprintf(rw_buf, sizeof(rw_buf), "%d %d %d %d\n", rf - orf, r - or, 584 | l - ol, lf - olf); 585 | buflen = strlen(rw_buf); 586 | count = buflen; 587 | len = buflen; 588 | 589 | /* copy data to user area */ 590 | if (copy_to_user((void *)buf, &rw_buf, count)) { 591 | printk(KERN_INFO "err read buffer from ret %d\n", ret); 592 | printk(KERN_INFO "err read buffer from %s\n", rw_buf); 593 | printk(KERN_INFO "err sample_char_read size(%zu)\n", count); 594 | printk(KERN_INFO "sample_char_read size err(%d)\n", -EFAULT); 595 | return 0; 596 | } 597 | 598 | *f_pos += count; 599 | 600 | return count; 601 | } 602 | 603 | /* --- Device File Operation --- */ 604 | /* Open Device */ 605 | static int dev_open(struct inode *inode, struct file *filep) 606 | { 607 | int *minor = (int *)kmalloc(sizeof(int), GFP_KERNEL); 608 | int major = MAJOR(inode->i_rdev); 609 | *minor = MINOR(inode->i_rdev); 610 | 611 | filep->private_data = (void *)minor; 612 | 613 | const char *dev_name = filep->f_path.dentry->d_name.name; 614 | printk(KERN_INFO "Device opened: %s, Major: %d\n", dev_name, major); 615 | 616 | return 0; 617 | } 618 | 619 | /* Close device */ 620 | static int dev_release(struct inode *inode, struct file *filep) 621 | { 622 | kfree(filep->private_data); 623 | return 0; 624 | } 625 | 626 | static int i2c_dev_open(struct inode *inode, struct file *filep) 627 | { 628 | struct rtcnt_device_info *dev_info; 629 | dev_info = container_of(inode->i_cdev, struct rtcnt_device_info, cdev); 630 | if (dev_info == NULL || dev_info->client == NULL) { 631 | printk(KERN_ERR "%s: i2c dev_open failed.\n", DRIVER_NAME); 632 | } 633 | dev_info->device_minor = MINOR(inode->i_rdev); 634 | filep->private_data = dev_info; 635 | return 0; 636 | } 637 | 638 | static int i2c_dev_release(struct inode *inode, struct file *filep) 639 | { 640 | return 0; 641 | } 642 | 643 | /* 644 | * led_write - Trun ON/OFF LEDs 645 | * Write function of /dev/rtled 646 | */ 647 | static ssize_t led_write(struct file *filep, const char __user *buf, 648 | size_t count, loff_t *f_pos) 649 | { 650 | char cval; 651 | int ret; 652 | int minor = *((int *)filep->private_data); 653 | 654 | if (count > 0) { 655 | if (copy_from_user(&cval, buf, sizeof(char))) { 656 | return -EFAULT; 657 | } 658 | switch (cval) { 659 | case '1': 660 | ret = led_put(minor); 661 | break; 662 | case '0': 663 | ret = led_del(minor); 664 | break; 665 | } 666 | return sizeof(char); 667 | } 668 | return 0; 669 | } 670 | 671 | /* 672 | * buzzer_write - Write buzzer frequency 673 | * Write function of /dev/rtbuzzer 674 | */ 675 | static ssize_t buzzer_write(struct file *filep, const char __user *buf, 676 | size_t count, loff_t *f_pos) 677 | { 678 | int ret; 679 | int freq, dat; 680 | 681 | ret = kstrtoint_from_user(buf, count, 10, &freq); 682 | if (ret) { 683 | printk(KERN_ERR "%s: error parsing string to int in %s()\n", 684 | DRIVER_NAME, __func__); 685 | return ret; 686 | } 687 | 688 | if (freq != 0) { 689 | if (freq < 1) { 690 | freq = 1; 691 | } 692 | 693 | if (freq > 20000) { 694 | freq = 20000; 695 | } 696 | 697 | rpi_gpio_function_set(BUZZER_BASE, 698 | RPI_GPF_ALT5); // io is pwm out 699 | dat = PWM_BASECLK / freq; 700 | rpi_pwm_write32(RPI_PWM_RNG2, dat); 701 | rpi_pwm_write32(RPI_PWM_DAT2, dat >> 1); 702 | } else { 703 | rpi_gpio_function_set(BUZZER_BASE, 704 | RPI_GPF_OUTPUT); // io is pwm out 705 | } 706 | 707 | return count; 708 | } 709 | 710 | /* 711 | * Initialize buzzer 712 | * return 0 : device close 713 | */ 714 | int buzzer_init(void) 715 | { 716 | 717 | rpi_gpio_function_set(BUZZER_BASE, RPI_GPF_OUTPUT); // io is pwm out 718 | rpi_pwm_write32(RPI_PWM_CTRL, 0x00000000); 719 | udelay(1000); 720 | rpi_pwm_write32(RPI_PWM_CTRL, 0x00008181); // PWM1,2 enable 721 | 722 | // printk(KERN_DEBUG "%s: rpi_pwm_ctrl:%08X\n", DRIVER_NAME, 723 | // ioread32(pwm_base + RPI_PWM_CTRL)); 724 | 725 | return 0; 726 | } 727 | 728 | /* 729 | * rawmotor_l_write - Output frequency to the left motor 730 | * Write function of /dev/rtmotor_raw_l 731 | */ 732 | static ssize_t rawmotor_l_write(struct file *filep, const char __user *buf, 733 | size_t count, loff_t *f_pos) 734 | { 735 | int freq, ret; 736 | 737 | ret = kstrtoint_from_user(buf, count, 10, &freq); 738 | if (ret) { 739 | printk(KERN_ERR "%s: error parsing string to int in %s()\n", 740 | DRIVER_NAME, __func__); 741 | return ret; 742 | } 743 | set_motor_freq(freq, DEV_LEFT); 744 | 745 | return count; 746 | } 747 | 748 | /* 749 | * rawmotor_r_write - Output frequency to the right motor 750 | * Write function of /dev/rtmotor_raw_r 751 | */ 752 | static ssize_t rawmotor_r_write(struct file *filep, const char __user *buf, 753 | size_t count, loff_t *f_pos) 754 | { 755 | int freq, ret; 756 | 757 | ret = kstrtoint_from_user(buf, count, 10, &freq); 758 | if (ret) { 759 | printk(KERN_ERR "%s: error parsing string to int in %s()\n", 760 | DRIVER_NAME, __func__); 761 | return ret; 762 | } 763 | 764 | set_motor_freq(freq, DEV_RIGHT); 765 | 766 | return count; 767 | } 768 | 769 | /* 770 | * motoren_write - Turn ON/OFF SteppingMotor Power 771 | * Write function of /dev/rtmotoren 772 | */ 773 | static ssize_t motoren_write(struct file *filep, const char __user *buf, 774 | size_t count, loff_t *f_pos) 775 | { 776 | char cval; 777 | 778 | if (count > 0) { 779 | if (copy_from_user(&cval, buf, sizeof(char))) { 780 | return -EFAULT; 781 | } 782 | 783 | switch (cval) { 784 | case '1': 785 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << MOTEN_BASE); 786 | break; 787 | case '0': 788 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << MOTEN_BASE); 789 | break; 790 | } 791 | return sizeof(char); 792 | } 793 | return 0; 794 | } 795 | 796 | /* 797 | * motor_write - Output frequency to right and left both motors 798 | * Write function of /dev/rtmotor 799 | */ 800 | static ssize_t motor_write(struct file *filep, const char __user *buf, 801 | size_t count, loff_t *f_pos) 802 | { 803 | int tmp; 804 | int bufcnt; 805 | bufcnt = parseMotorCmd(buf, count, &tmp); 806 | 807 | return bufcnt; 808 | } 809 | 810 | /* 811 | * Device File Operations 812 | * used in register_dev(), rtcntr_i2c_create_cdev() 813 | * and rtcntl_i2c_create_cdev() 814 | */ 815 | struct file_operations dev_fops[ID_DEV_SIZE] = { 816 | [ID_DEV_LED].open = dev_open, 817 | [ID_DEV_LED].release = dev_release, 818 | [ID_DEV_LED].write = led_write, 819 | [ID_DEV_SWITCH].open = dev_open, 820 | [ID_DEV_SWITCH].read = sw_read, 821 | [ID_DEV_SWITCH].release = dev_release, 822 | [ID_DEV_SENSOR].open = dev_open, 823 | [ID_DEV_SENSOR].read = sensor_read, 824 | [ID_DEV_SENSOR].release = dev_release, 825 | [ID_DEV_BUZZER].open = dev_open, 826 | [ID_DEV_BUZZER].release = dev_release, 827 | [ID_DEV_BUZZER].write = buzzer_write, 828 | [ID_DEV_MOTORRAWR].open = dev_open, 829 | [ID_DEV_MOTORRAWR].release = dev_release, 830 | [ID_DEV_MOTORRAWR].write = rawmotor_r_write, 831 | [ID_DEV_MOTORRAWL].open = dev_open, 832 | [ID_DEV_MOTORRAWL].release = dev_release, 833 | [ID_DEV_MOTORRAWL].write = rawmotor_l_write, 834 | [ID_DEV_MOTOREN].open = dev_open, 835 | [ID_DEV_MOTOREN].release = dev_release, 836 | [ID_DEV_MOTOREN].write = motoren_write, 837 | [ID_DEV_MOTOR].open = dev_open, 838 | [ID_DEV_MOTOR].release = dev_release, 839 | [ID_DEV_MOTOR].write = motor_write, 840 | [ID_DEV_CNT].open = i2c_dev_open, 841 | [ID_DEV_CNT].release = i2c_dev_release, 842 | [ID_DEV_CNT].read = rtcnt_read, 843 | [ID_DEV_CNT].write = rtcnt_write}; 844 | 845 | /* --- Device Driver Registration and Device File Creation --- */ 846 | int register_dev(int id_dev) 847 | { 848 | int retval; 849 | dev_t dev; 850 | dev_t devno; 851 | int i; 852 | 853 | /* 空いているメジャー番号を使ってメジャー& 854 | マイナー番号をカーネルに登録する */ 855 | retval = 856 | alloc_chrdev_region(&dev, /* 結果を格納するdev_t構造体 */ 857 | DEV_MINOR, /* ベースマイナー番号 */ 858 | NUM_DEV[id_dev], /* デバイスの数 */ 859 | NAME_DEV[id_dev] /* デバイスドライバの名前 */ 860 | ); 861 | 862 | if (retval < 0) { 863 | printk(KERN_ERR "alloc_chrdev_region failed.\n"); 864 | return retval; 865 | } 866 | _major_dev[id_dev] = MAJOR(dev); 867 | 868 | /* デバイスクラスを作成する */ 869 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0) 870 | class_dev[id_dev] = class_create(THIS_MODULE, NAME_DEV[id_dev]); 871 | #else 872 | class_dev[id_dev] = class_create(NAME_DEV[id_dev]); 873 | #endif 874 | 875 | if (IS_ERR(class_dev[id_dev])) { 876 | return PTR_ERR(class_dev[id_dev]); 877 | } 878 | 879 | for (i = 0; i < NUM_DEV[id_dev]; i++) { 880 | /* デバイスの数だけキャラクタデバイスを登録する */ 881 | devno = MKDEV(_major_dev[id_dev], _minor_dev[id_dev] + i); 882 | 883 | /* キャラクタデバイスとしてこのモジュールをカーネルに登録する */ 884 | cdev_init(&(cdev_array[cdev_index]), &dev_fops[id_dev]); 885 | cdev_array[cdev_index].owner = THIS_MODULE; 886 | if (cdev_add(&(cdev_array[cdev_index]), devno, 1) < 0) { 887 | /* 登録に失敗した */ 888 | printk(KERN_ERR "cdev_add failed minor = %d\n", 889 | _minor_dev[id_dev] + i); 890 | } else { 891 | /* デバイスノードの作成 */ 892 | struct device *dev_ret; 893 | dev_ret = device_create(class_dev[id_dev], NULL, devno, 894 | NULL, NAME_DEV_U[id_dev], 895 | _minor_dev[id_dev] + i); 896 | 897 | /* デバイスファイル作成の可否を判定 */ 898 | if (IS_ERR(dev_ret)) { 899 | /* デバイスファイルの作成に失敗した */ 900 | printk(KERN_ERR 901 | "device_create failed minor = %d\n", 902 | _minor_dev[id_dev] + i); 903 | /* リソースリークを避けるために登録された状態cdevを削除する 904 | */ 905 | cdev_del(&(cdev_array[cdev_index])); 906 | return PTR_ERR(dev_ret); 907 | } 908 | } 909 | cdev_index++; 910 | } 911 | return 0; 912 | } 913 | -------------------------------------------------------------------------------- /src/drivers/rtmouse_gpio.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse_gpio.c 4 | * GPIO driver 5 | * 6 | * Copyright (C) 2024 RT Corporation 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; version 2. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | * MA 02110-1301, USA. 21 | */ 22 | 23 | #include "rtmouse.h" 24 | 25 | static volatile void __iomem *clk_base; 26 | 27 | /* 28 | * set function 29 | * called by buzzer_init(), set_motor_l_freq(), set_motor_r_freq() and 30 | * buzzer_write() 31 | */ 32 | int rpi_gpio_function_set(int pin, uint32_t func) 33 | { 34 | int index = RPI_GPFSEL0_INDEX + pin / 10; 35 | uint32_t mask = ~(0x7 << ((pin % 10) * 3)); 36 | 37 | gpio_base[index] = 38 | (gpio_base[index] & mask) | ((func & 0x7) << ((pin % 10) * 3)); 39 | 40 | return 1; 41 | } 42 | 43 | /* 44 | * set mask and value 45 | * called by sensor_read(), set_motor_l_freq(), set_motor_r_freq(), led_put() 46 | * and motoren_write() 47 | */ 48 | void rpi_gpio_set32(uint32_t mask, uint32_t val) 49 | { 50 | gpio_base[RPI_GPSET0_INDEX] = val & mask; 51 | } 52 | 53 | /* 54 | * clear mask and value 55 | * called by sensor_read(), set_motor_l_freq(), set_motor_r_freq(), led_del() 56 | * and motoren_write() 57 | */ 58 | void rpi_gpio_clear32(uint32_t mask, uint32_t val) 59 | { 60 | gpio_base[RPI_GPCLR0_INDEX] = val & mask; 61 | } 62 | 63 | /* 64 | * pwm set function 65 | * called by buzzer_init(), set_motor_l_freq(), set_motor_r_freq() 66 | * and buzzer_write() 67 | */ 68 | void rpi_pwm_write32(uint32_t offset, uint32_t val) 69 | { 70 | iowrite32(val, pwm_base + offset); 71 | } 72 | 73 | /* --- GPIO mapping for Device Open/Close --- */ 74 | /* 75 | * Get gpio addresses and set them to global variables. 76 | * - gpio_base 77 | * - pwm_base 78 | * - clk_base 79 | * - clk_status 80 | */ 81 | int gpio_map(void) 82 | { 83 | static int clk_status = 1; 84 | 85 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 0, 0) 86 | if (gpio_base == NULL) { 87 | gpio_base = ioremap_nocache(RPI_GPIO_BASE, RPI_GPIO_SIZE); 88 | } 89 | 90 | if (pwm_base == NULL) { 91 | pwm_base = ioremap_nocache(RPI_PWM_BASE, RPI_PWM_SIZE); 92 | } 93 | 94 | if (clk_base == NULL) { 95 | clk_base = ioremap_nocache(RPI_CLK_BASE, RPI_CLK_SIZE); 96 | } 97 | #else 98 | if (gpio_base == NULL) { 99 | gpio_base = ioremap(RPI_GPIO_BASE, RPI_GPIO_SIZE); 100 | } 101 | 102 | if (pwm_base == NULL) { 103 | pwm_base = ioremap(RPI_PWM_BASE, RPI_PWM_SIZE); 104 | } 105 | 106 | if (clk_base == NULL) { 107 | clk_base = ioremap(RPI_CLK_BASE, RPI_CLK_SIZE); 108 | } 109 | #endif 110 | 111 | /* kill */ 112 | if (clk_status == 1) { 113 | iowrite32(0x5a000000 | (1 << 5), clk_base + CLK_PWM_INDEX); 114 | udelay(1000); 115 | 116 | /* clk set */ 117 | iowrite32(0x5a000000 | (2 << 12), clk_base + CLK_PWMDIV_INDEX); 118 | iowrite32(0x5a000011, clk_base + CLK_PWM_INDEX); 119 | 120 | udelay(1000); /* wait for 1msec */ 121 | 122 | clk_status = 0; 123 | } 124 | 125 | return 0; 126 | } 127 | 128 | /* Unmap GPIO addresses */ 129 | int gpio_unmap(void) 130 | { 131 | iounmap(gpio_base); 132 | iounmap(pwm_base); 133 | iounmap(clk_base); 134 | 135 | gpio_base = NULL; 136 | pwm_base = NULL; 137 | clk_base = NULL; 138 | return 0; 139 | } 140 | -------------------------------------------------------------------------------- /src/drivers/rtmouse_i2c.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse_i2c.c 4 | * I2C driver 5 | * 6 | * Copyright (C) 2024 RT Corporation 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; version 2. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | * MA 02110-1301, USA. 21 | */ 22 | 23 | #include "rtmouse.h" 24 | 25 | /* --- Function Declarations --- */ 26 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) 27 | static int rtcnt_i2c_probe(struct i2c_client *client, 28 | const struct i2c_device_id *id); 29 | #else 30 | static int rtcnt_i2c_probe(struct i2c_client *client); 31 | #endif 32 | 33 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) 34 | static int rtcnt_i2c_remove(struct i2c_client *client); 35 | #else 36 | static void rtcnt_i2c_remove(struct i2c_client *client); 37 | #endif 38 | 39 | // used in i2c_counter_init() and i2c_counter_exit() 40 | static struct i2c_client *i2c_client_r = NULL; 41 | static struct i2c_client *i2c_client_l = NULL; 42 | 43 | /* 44 | * I2C Device ID 45 | * used in i2c_counter_driver 46 | */ 47 | static struct i2c_device_id i2c_counter_id[] = { 48 | {DEVNAME_CNTL, 0}, 49 | {DEVNAME_CNTR, 1}, 50 | {}, 51 | }; 52 | 53 | /* 54 | * I2C Dirver Info 55 | * used in i2c_counter_init() and i2c_counter_exit() 56 | */ 57 | static struct i2c_driver i2c_counter_driver = { 58 | .driver = 59 | { 60 | .name = "rtcounter", 61 | .owner = THIS_MODULE, 62 | }, 63 | .id_table = i2c_counter_id, 64 | .probe = rtcnt_i2c_probe, 65 | .remove = rtcnt_i2c_remove, 66 | }; 67 | 68 | /* -- Device Addition -- */ 69 | MODULE_DEVICE_TABLE(i2c, i2c_counter_id); 70 | 71 | // called by rtcnt_i2c_probe() 72 | static int rtcnt_i2c_create_cdev(struct rtcnt_device_info *dev_info, 73 | const int dev_side) 74 | { 75 | int minor; 76 | int alloc_ret = 0; 77 | int cdev_err = 0; 78 | dev_t dev; 79 | 80 | /* 空いているメジャー番号を確保する */ 81 | if (dev_side == DEV_LEFT) { 82 | alloc_ret = alloc_chrdev_region( 83 | &dev, DEV_MINOR, NUM_DEV[ID_DEV_CNT], DEVNAME_CNTL); 84 | } else if (dev_side == DEV_RIGHT) { 85 | alloc_ret = alloc_chrdev_region( 86 | &dev, DEV_MINOR, NUM_DEV[ID_DEV_CNT], DEVNAME_CNTR); 87 | } 88 | if (alloc_ret != 0) { 89 | printk(KERN_ERR "alloc_chrdev_region = %d\n", alloc_ret); 90 | return -1; 91 | } 92 | 93 | /* 取得したdev( = メジャー番号 + マイナー番号) 94 | * からメジャー番号を取得して保持しておく */ 95 | dev_info->device_major = MAJOR(dev); 96 | dev = MKDEV(dev_info->device_major, DEV_MINOR); 97 | 98 | /* cdev構造体の初期化とシステムコールハンドラテーブルの登録 */ 99 | cdev_init(&dev_info->cdev, &dev_fops[ID_DEV_CNT]); 100 | dev_info->cdev.owner = THIS_MODULE; 101 | 102 | /* このデバイスドライバ(cdev)をカーネルに登録する */ 103 | cdev_err = cdev_add(&dev_info->cdev, dev, NUM_DEV[ID_DEV_CNT]); 104 | if (cdev_err != 0) { 105 | printk(KERN_ERR "cdev_add = %d\n", alloc_ret); 106 | unregister_chrdev_region(dev, NUM_DEV[ID_DEV_CNT]); 107 | return -1; 108 | } 109 | 110 | /* このデバイスのクラス登録をする(/sys/class/mydevice/ を作る) */ 111 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 4, 0) 112 | if (dev_side == DEV_LEFT) { 113 | dev_info->device_class = 114 | class_create(THIS_MODULE, DEVNAME_CNTL); 115 | } else if (dev_side == DEV_RIGHT) { 116 | dev_info->device_class = 117 | class_create(THIS_MODULE, DEVNAME_CNTR); 118 | } 119 | #else 120 | if (dev_side == DEV_LEFT) { 121 | dev_info->device_class = class_create(DEVNAME_CNTL); 122 | } else if (dev_side == DEV_RIGHT) { 123 | dev_info->device_class = class_create(DEVNAME_CNTR); 124 | } 125 | #endif 126 | 127 | if (IS_ERR(dev_info->device_class)) { 128 | printk(KERN_ERR "class_create\n"); 129 | cdev_del(&dev_info->cdev); 130 | unregister_chrdev_region(dev, NUM_DEV[ID_DEV_CNT]); 131 | return -1; 132 | } 133 | 134 | /* /sys/class/mydevice/mydevice* を作る */ 135 | for (minor = DEV_MINOR; minor < DEV_MINOR + NUM_DEV[ID_DEV_CNT]; 136 | minor++) { 137 | 138 | struct device *dev_ret; 139 | if (dev_side == DEV_LEFT) { 140 | dev_ret = 141 | device_create(dev_info->device_class, NULL, 142 | MKDEV(dev_info->device_major, minor), 143 | NULL, "rtcounter_l%d", minor); 144 | } else if (dev_side == DEV_RIGHT) { 145 | dev_ret = 146 | device_create(dev_info->device_class, NULL, 147 | MKDEV(dev_info->device_major, minor), 148 | NULL, "rtcounter_r%d", minor); 149 | } 150 | 151 | /* デバイスファイル作成の可否を判定 */ 152 | if (IS_ERR(dev_ret)) { 153 | /* デバイスファイルの作成に失敗した */ 154 | printk(KERN_ERR "device_create failed minor = %d\n", 155 | minor); 156 | /* リソースリークを避けるために登録された状態cdevを削除する 157 | */ 158 | cdev_del(&(cdev_array[cdev_index])); 159 | return PTR_ERR(dev_ret); 160 | } 161 | } 162 | 163 | return 0; 164 | } 165 | 166 | // called by rtcnt_i2c_remove() 167 | static void rtcnt_i2c_delete_cdev(struct rtcnt_device_info *dev_info) 168 | { 169 | dev_t dev = MKDEV(dev_info->device_major, DEV_MINOR); 170 | int minor; 171 | /* /sys/class/mydevice/mydevice* を削除する */ 172 | for (minor = DEV_MINOR; minor < DEV_MINOR + NUM_DEV[ID_DEV_CNT]; 173 | minor++) { 174 | device_destroy(dev_info->device_class, 175 | MKDEV(dev_info->device_major, minor)); 176 | } 177 | /* このデバイスのクラス登録を取り除く(/sys/class/mydevice/を削除する) */ 178 | class_destroy(dev_info->device_class); 179 | /* このデバイスドライバ(cdev)をカーネルから取り除く */ 180 | cdev_del(&dev_info->cdev); 181 | /* このデバイスドライバで使用していたメジャー番号の登録を取り除く */ 182 | unregister_chrdev_region(dev, NUM_DEV[ID_DEV_CNT]); 183 | } 184 | 185 | // called by i2c_counter_driver() 186 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 2, 0) 187 | static int rtcnt_i2c_probe(struct i2c_client *client, 188 | const struct i2c_device_id *id) 189 | { 190 | struct rtcnt_device_info *dev_info; 191 | int msb = 0, lsb = 0; 192 | // printk(KERN_DEBUG "%s: probing i2c device", __func__); 193 | 194 | /* check i2c device */ 195 | // printk(KERN_DEBUG "%s: checking i2c device", __func__); 196 | msb = i2c_smbus_read_byte_data(client, CNT_ADDR_MSB); 197 | lsb = i2c_smbus_read_byte_data(client, CNT_ADDR_LSB); 198 | if ((msb < 0) || (lsb < 0)) { 199 | printk(KERN_INFO 200 | "%s: rtcounter not found, or wrong i2c device probed", 201 | DRIVER_NAME); 202 | // printk(KERN_DEBUG "%s: addr 0x%x, msb %d, lsb %d", __func__, 203 | // client->addr, msb, lsb); 204 | return -ENODEV; 205 | } 206 | printk(KERN_INFO "%s: new i2c device probed, id.name=%s, " 207 | "id.driver_data=%d, addr=0x%x\n", 208 | DRIVER_NAME, id->name, (int)(id->driver_data), client->addr); 209 | 210 | dev_info = (struct rtcnt_device_info *)devm_kzalloc( 211 | &client->dev, sizeof(struct rtcnt_device_info), GFP_KERNEL); 212 | dev_info->client = client; 213 | i2c_set_clientdata(client, dev_info); 214 | mutex_init(&dev_info->lock); 215 | 216 | /* create character device */ 217 | if ((int)(id->driver_data) == 0) { 218 | if (rtcnt_i2c_create_cdev(dev_info, DEV_LEFT)) 219 | return -ENOMEM; 220 | } else if ((int)(id->driver_data) == 1) { 221 | if (rtcnt_i2c_create_cdev(dev_info, DEV_RIGHT)) 222 | return -ENOMEM; 223 | } 224 | 225 | return 0; 226 | } 227 | #else 228 | static int rtcnt_i2c_probe(struct i2c_client *client) 229 | { 230 | const struct i2c_device_id *id = i2c_client_get_device_id(client); 231 | struct rtcnt_device_info *dev_info; 232 | int msb = 0, lsb = 0; 233 | // printk(KERN_DEBUG "%s: probing i2c device", __func__); 234 | 235 | /* check i2c device */ 236 | // printk(KERN_DEBUG "%s: checking i2c device", __func__); 237 | msb = i2c_smbus_read_byte_data(client, CNT_ADDR_MSB); 238 | lsb = i2c_smbus_read_byte_data(client, CNT_ADDR_LSB); 239 | if ((msb < 0) || (lsb < 0)) { 240 | printk(KERN_INFO 241 | "%s: rtcounter not found, or wrong i2c device probed", 242 | DRIVER_NAME); 243 | // printk(KERN_DEBUG "%s: addr 0x%x, msb %d, lsb %d", __func__, 244 | // client->addr, msb, lsb); 245 | return -ENODEV; 246 | } 247 | printk(KERN_INFO "%s: new i2c device probed, id.name=%s, " 248 | "id.driver_data=%d, addr=0x%x\n", 249 | DRIVER_NAME, id->name, (int)(id->driver_data), client->addr); 250 | 251 | dev_info = (struct rtcnt_device_info *)devm_kzalloc( 252 | &client->dev, sizeof(struct rtcnt_device_info), GFP_KERNEL); 253 | dev_info->client = client; 254 | i2c_set_clientdata(client, dev_info); 255 | mutex_init(&dev_info->lock); 256 | 257 | /* create character device */ 258 | if ((int)(id->driver_data) == 0) { 259 | if (rtcnt_i2c_create_cdev(dev_info, DEV_LEFT)) 260 | return -ENOMEM; 261 | } else if ((int)(id->driver_data) == 1) { 262 | if (rtcnt_i2c_create_cdev(dev_info, DEV_RIGHT)) 263 | return -ENOMEM; 264 | } 265 | 266 | return 0; 267 | } 268 | #endif 269 | 270 | /* 271 | * i2c_counter_remove - I2C pulse counter 272 | * called when I2C pulse counter removed 273 | * called by i2c_counter_driver() 274 | */ 275 | #if LINUX_VERSION_CODE < KERNEL_VERSION(6, 1, 0) 276 | static int rtcnt_i2c_remove(struct i2c_client *client) 277 | { 278 | struct rtcnt_device_info *dev_info; 279 | // printk(KERN_DEBUG "%s: removing i2c device 0x%x\n", __func__, 280 | // client->addr); 281 | dev_info = i2c_get_clientdata(client); 282 | rtcnt_i2c_delete_cdev(dev_info); 283 | printk(KERN_INFO "%s: i2c device 0x%x removed\n", DRIVER_NAME, 284 | client->addr); 285 | return 0; 286 | } 287 | #else 288 | static void rtcnt_i2c_remove(struct i2c_client *client) 289 | { 290 | struct rtcnt_device_info *dev_info; 291 | // printk(KERN_DEBUG "%s: removing i2c device 0x%x\n", __func__, 292 | // client->addr); 293 | dev_info = i2c_get_clientdata(client); 294 | rtcnt_i2c_delete_cdev(dev_info); 295 | printk(KERN_INFO "%s: i2c device 0x%x removed\n", DRIVER_NAME, 296 | client->addr); 297 | } 298 | #endif 299 | 300 | /* 301 | * i2c_counter_init - initialize I2C counter 302 | * called by dev_init_module() 303 | */ 304 | int i2c_counter_init(void) 305 | { 306 | int retval = 0; 307 | struct i2c_adapter *i2c_adap_l; 308 | struct i2c_adapter *i2c_adap_r; 309 | struct i2c_board_info i2c_board_info_l = { 310 | I2C_BOARD_INFO(DEVNAME_CNTL, DEV_ADDR_CNTL)}; 311 | struct i2c_board_info i2c_board_info_r = { 312 | I2C_BOARD_INFO(DEVNAME_CNTR, DEV_ADDR_CNTR)}; 313 | 314 | // printk(KERN_DEBUG "%s: initializing i2c device", __func__); 315 | retval = i2c_add_driver(&i2c_counter_driver); 316 | if (retval != 0) { 317 | printk(KERN_INFO "%s: failed adding i2c device", DRIVER_NAME); 318 | return retval; 319 | } 320 | 321 | /* 322 | * 動的にデバイス実体を作成 323 | * (https://www.kernel.org/doc/Documentation/i2c/instantiating-devices) 324 | */ 325 | #if LINUX_VERSION_CODE <= KERNEL_VERSION(5, 0, 0) 326 | // printk(KERN_DEBUG "%s: adding i2c device", __func__); 327 | i2c_adap_l = i2c_get_adapter(1); 328 | i2c_client_l = i2c_new_device(i2c_adap_l, &i2c_board_info_l); 329 | i2c_put_adapter(i2c_adap_l); 330 | // printk(KERN_DEBUG "%s: added i2c device rtcntl", __func__); 331 | 332 | // printk(KERN_DEBUG "%s: adding i2c device", __func__); 333 | i2c_adap_r = i2c_get_adapter(1); 334 | i2c_client_r = i2c_new_device(i2c_adap_r, &i2c_board_info_r); 335 | i2c_put_adapter(i2c_adap_r); 336 | // printk(KERN_DEBUG "%s: added i2c device rtcntr", __func__); 337 | #else 338 | // printk(KERN_DEBUG "%s: adding i2c device", __func__); 339 | i2c_adap_l = i2c_get_adapter(1); 340 | i2c_client_l = i2c_new_client_device(i2c_adap_l, &i2c_board_info_l); 341 | i2c_put_adapter(i2c_adap_l); 342 | // printk(KERN_DEBUG "%s: added i2c device rtcntl", __func__); 343 | 344 | // printk(KERN_DEBUG "%s: adding i2c device", __func__); 345 | i2c_adap_r = i2c_get_adapter(1); 346 | i2c_client_r = i2c_new_client_device(i2c_adap_r, &i2c_board_info_r); 347 | i2c_put_adapter(i2c_adap_r); 348 | // printk(KERN_DEBUG "%s: added i2c device rtcntr", __func__); 349 | #endif 350 | 351 | return retval; 352 | } 353 | 354 | /* 355 | * i2c_counter_exit - cleanup I2C device 356 | * called by dev_cleanup_module() 357 | */ 358 | void i2c_counter_exit(void) 359 | { 360 | /* delete I2C driver */ 361 | i2c_del_driver(&i2c_counter_driver); 362 | /* free memory */ 363 | if (i2c_client_r) 364 | i2c_unregister_device(i2c_client_r); 365 | if (i2c_client_l) 366 | i2c_unregister_device(i2c_client_l); 367 | } 368 | -------------------------------------------------------------------------------- /src/drivers/rtmouse_main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse_main.c 4 | * Raspberry Pi Mouse device driver 5 | * 6 | * Version: 3.3.4 7 | * 8 | * Copyright (C) 2015-2024 RT Corporation 9 | * 10 | * This program is free software; you can redistribute it and/or modify 11 | * it under the terms of the GNU General Public License as published by 12 | * the Free Software Foundation; version 2. 13 | * 14 | * This program is distributed in the hope that it will be useful, 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | * GNU General Public License for more details. 18 | * 19 | * You should have received a copy of the GNU General Public License 20 | * along with this program; if not, write to the Free Software 21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 22 | * MA 02110-1301, USA. 23 | */ 24 | 25 | #include "rtmouse.h" 26 | 27 | MODULE_AUTHOR("RT Corporation"); 28 | MODULE_LICENSE("GPL"); 29 | MODULE_VERSION("3.3.4"); 30 | MODULE_DESCRIPTION("Raspberry Pi Mouse device driver"); 31 | 32 | /* 33 | * --- Device Numbers --- 34 | * used in rtmouse_i2c.c, dev_init_module() 35 | * and cleanup_each_dev() 36 | */ 37 | const unsigned int NUM_DEV[ID_DEV_SIZE] = { 38 | [ID_DEV_LED] = 4, [ID_DEV_SWITCH] = 3, [ID_DEV_SENSOR] = 1, 39 | [ID_DEV_BUZZER] = 1, [ID_DEV_MOTORRAWR] = 1, [ID_DEV_MOTORRAWL] = 1, 40 | [ID_DEV_MOTOREN] = 1, [ID_DEV_MOTOR] = 1, [ID_DEV_CNT] = 2}; 41 | 42 | /* 43 | * --- Device Names --- 44 | * used in rtmouse_dev.c and dev_init_module() 45 | */ 46 | const char *NAME_DEV[ID_DEV_SIZE] = {[ID_DEV_LED] = "rtled", 47 | [ID_DEV_SWITCH] = "rtswitch", 48 | [ID_DEV_SENSOR] = "rtlightsensor", 49 | [ID_DEV_BUZZER] = "rtbuzzer", 50 | [ID_DEV_MOTORRAWR] = "rtmotor_raw_r", 51 | [ID_DEV_MOTORRAWL] = "rtmotor_raw_l", 52 | [ID_DEV_MOTOREN] = "rtmotoren", 53 | [ID_DEV_MOTOR] = "rtmotor"}; 54 | 55 | // used in by rtmouse_dev.c and cleanup_each_dev() 56 | int _major_dev[ID_DEV_SIZE] = { 57 | [ID_DEV_LED] = DEV_MAJOR, [ID_DEV_SWITCH] = DEV_MAJOR, 58 | [ID_DEV_SENSOR] = DEV_MAJOR, [ID_DEV_BUZZER] = DEV_MAJOR, 59 | [ID_DEV_MOTORRAWR] = DEV_MAJOR, [ID_DEV_MOTORRAWL] = DEV_MAJOR, 60 | [ID_DEV_MOTOREN] = DEV_MAJOR, [ID_DEV_MOTOR] = DEV_MAJOR}; 61 | 62 | // used in rtmouse_dev.c and cleanup_each_dev() 63 | int _minor_dev[ID_DEV_SIZE] = { 64 | [ID_DEV_LED] = DEV_MINOR, [ID_DEV_SWITCH] = DEV_MINOR, 65 | [ID_DEV_SENSOR] = DEV_MINOR, [ID_DEV_BUZZER] = DEV_MINOR, 66 | [ID_DEV_MOTORRAWR] = DEV_MINOR, [ID_DEV_MOTORRAWL] = DEV_MINOR, 67 | [ID_DEV_MOTOREN] = DEV_MINOR, [ID_DEV_MOTOR] = DEV_MINOR}; 68 | 69 | /* 70 | * --- General Options --- 71 | * used in rtmouse_dev.c and dev_cleanup_module() 72 | */ 73 | struct class *class_dev[ID_DEV_SIZE] = { 74 | [ID_DEV_LED] = NULL, [ID_DEV_SWITCH] = NULL, 75 | [ID_DEV_SENSOR] = NULL, [ID_DEV_BUZZER] = NULL, 76 | [ID_DEV_MOTORRAWR] = NULL, [ID_DEV_MOTORRAWL] = NULL, 77 | [ID_DEV_MOTOREN] = NULL, [ID_DEV_MOTOR] = NULL}; 78 | 79 | // used in rtmouse_i2c.c and dev_cleanup_module() 80 | struct cdev *cdev_array = NULL; 81 | 82 | // used in rtmouse_i2c.c 83 | volatile int cdev_index = 0; 84 | 85 | // used in rtmouse_dev.c and rtmouse_gpio.c 86 | volatile void __iomem *pwm_base; 87 | volatile uint32_t *gpio_base; 88 | 89 | // used in rtmouse_dev.c, rtmouse_i2c.c and rtmouse_spi.c 90 | struct mutex lock; 91 | 92 | /* --- Static variables --- */ 93 | // used in rtmouse_dev.c and rtmouse_spi.c 94 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 95 | struct device *mcp320x_dev; 96 | #endif 97 | 98 | /* 99 | * dev_init_module - register driver module 100 | * called by module_init(dev_init_module) 101 | */ 102 | static int dev_init_module(void) 103 | { 104 | int retval, i; 105 | int registered_devices = 0; 106 | size_t size; 107 | 108 | /* log loding message */ 109 | printk(KERN_INFO "%s: loading driver...\n", DRIVER_NAME); 110 | 111 | /* Initialize mutex lock */ 112 | mutex_init(&lock); 113 | 114 | retval = i2c_counter_init(); 115 | if (retval == 0) { 116 | registered_devices += 2 * NUM_DEV[ID_DEV_CNT]; 117 | } else { 118 | printk(KERN_ALERT 119 | "%s: i2c counter device driver register failed.\n", 120 | DRIVER_NAME); 121 | return retval; 122 | } 123 | 124 | /* GPIOレジスタがマップ可能か調べる */ 125 | retval = gpio_map(); 126 | if (retval != 0) { 127 | printk(KERN_ALERT "%s on %s: cannot use GPIO registers.\n", 128 | __func__, DRIVER_NAME); 129 | return -EBUSY; 130 | } 131 | 132 | /* GPIO初期化 */ 133 | // printk(KERN_DEBUG "%s: gpio initializing...\n", __func__); 134 | rpi_gpio_function_set(LED0_BASE, RPI_GPF_OUTPUT); 135 | rpi_gpio_function_set(LED1_BASE, RPI_GPF_OUTPUT); 136 | rpi_gpio_function_set(LED2_BASE, RPI_GPF_OUTPUT); 137 | rpi_gpio_function_set(LED3_BASE, RPI_GPF_OUTPUT); 138 | 139 | rpi_gpio_function_set(R_LED_BASE, RPI_GPF_OUTPUT); 140 | rpi_gpio_function_set(L_LED_BASE, RPI_GPF_OUTPUT); 141 | rpi_gpio_function_set(RF_LED_BASE, RPI_GPF_OUTPUT); 142 | rpi_gpio_function_set(LF_LED_BASE, RPI_GPF_OUTPUT); 143 | 144 | rpi_gpio_function_set(BUZZER_BASE, RPI_GPF_OUTPUT); 145 | rpi_gpio_function_set(MOTDIR_L_BASE, RPI_GPF_OUTPUT); 146 | rpi_gpio_function_set(MOTDIR_R_BASE, RPI_GPF_OUTPUT); 147 | rpi_gpio_function_set(MOTEN_BASE, RPI_GPF_OUTPUT); 148 | rpi_gpio_function_set(MOTCLK_L_BASE, RPI_GPF_OUTPUT); 149 | rpi_gpio_function_set(MOTCLK_L_BASE, RPI_GPF_OUTPUT); 150 | 151 | rpi_gpio_function_set(SW1_PIN, RPI_GPF_INPUT); 152 | rpi_gpio_function_set(SW2_PIN, RPI_GPF_INPUT); 153 | rpi_gpio_function_set(SW3_PIN, RPI_GPF_INPUT); 154 | 155 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << MOTEN_BASE); 156 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << MOTDIR_L_BASE); 157 | 158 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << R_LED_BASE); 159 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << L_LED_BASE); 160 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << RF_LED_BASE); 161 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << LF_LED_BASE); 162 | 163 | for (i = 0; i < 100; i++) { 164 | rpi_gpio_set32(RPI_GPIO_P2MASK, 1 << BUZZER_BASE); 165 | udelay(500); 166 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << BUZZER_BASE); 167 | udelay(500); 168 | } 169 | 170 | buzzer_init(); 171 | 172 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << R_LED_BASE); 173 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << L_LED_BASE); 174 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << RF_LED_BASE); 175 | rpi_gpio_clear32(RPI_GPIO_P2MASK, 1 << LF_LED_BASE); 176 | 177 | // printk(KERN_DEBUG "%s: gpio initialized\n", __func__); 178 | 179 | /* cdev構造体の用意 */ 180 | size = sizeof(struct cdev) * NUM_DEV_TOTAL; 181 | cdev_array = (struct cdev *)kmalloc(size, GFP_KERNEL); 182 | 183 | /* デバイスドライバをカーネルに登録 */ 184 | for (i = 0; i < ID_DEV_SIZE - 1; i++) { 185 | retval = register_dev(i); 186 | if (retval != 0) { 187 | printk(KERN_ALERT "%s: %s register failed.\n", 188 | DRIVER_NAME, NAME_DEV[i]); 189 | return retval; 190 | } 191 | } 192 | 193 | retval = mcp3204_init(); 194 | if (retval != 0) { 195 | printk(KERN_ALERT 196 | "%s: optical sensor driver register failed.\n", 197 | DRIVER_NAME); 198 | return retval; 199 | } 200 | 201 | printk(KERN_INFO "%s: %d devices loaded.\n", DRIVER_NAME, 202 | registered_devices + NUM_DEV_TOTAL); 203 | 204 | printk(KERN_INFO "%s: module installed at %lu\n", DRIVER_NAME, jiffies); 205 | return 0; 206 | } 207 | 208 | /* 209 | * dev_cleanup_module - cleanup driver module 210 | * called by module_exit(dev_cleanup_module) 211 | */ 212 | static void cleanup_each_dev(int id_dev) 213 | { 214 | int i; 215 | dev_t devno; 216 | dev_t devno_top; 217 | 218 | devno_top = MKDEV(_major_dev[id_dev], _minor_dev[id_dev]); 219 | for (i = 0; i < NUM_DEV[id_dev]; i++) { 220 | devno = MKDEV(_major_dev[id_dev], _minor_dev[id_dev] + i); 221 | device_destroy(class_dev[id_dev], devno); 222 | } 223 | unregister_chrdev_region(devno_top, NUM_DEV[id_dev]); 224 | } 225 | 226 | static void dev_cleanup_module(void) 227 | { 228 | int i; 229 | 230 | /* --- remove char device --- */ 231 | for (i = 0; i < NUM_DEV_TOTAL; i++) { 232 | cdev_del(&(cdev_array[i])); 233 | } 234 | 235 | /* --- free device num. and remove device --- */ 236 | for (i = 0; i < ID_DEV_SIZE - 1; i++) { 237 | cleanup_each_dev(i); 238 | } 239 | 240 | /* --- remove device node --- */ 241 | for (i = 0; i < ID_DEV_SIZE - 1; i++) { 242 | class_destroy(class_dev[i]); 243 | } 244 | 245 | /* remove MCP3204 */ 246 | mcp3204_exit(); 247 | 248 | /* remove I2C device */ 249 | i2c_counter_exit(); 250 | 251 | /* free cdev memory */ 252 | kfree(cdev_array); 253 | gpio_unmap(); 254 | printk(KERN_INFO "%s: module removed at %lu\n", DRIVER_NAME, jiffies); 255 | } 256 | 257 | /* --- MAIN PROCESS --- */ 258 | module_init(dev_init_module); 259 | module_exit(dev_cleanup_module); 260 | -------------------------------------------------------------------------------- /src/drivers/rtmouse_spi.c: -------------------------------------------------------------------------------- 1 | /* 2 | * 3 | * rtmouse_spi.c 4 | * SPI driver 5 | * 6 | * Copyright (C) 2024 RT Corporation 7 | * 8 | * This program is free software; you can redistribute it and/or modify 9 | * it under the terms of the GNU General Public License as published by 10 | * the Free Software Foundation; version 2. 11 | * 12 | * This program is distributed in the hope that it will be useful, 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | * GNU General Public License for more details. 16 | * 17 | * You should have received a copy of the GNU General Public License 18 | * along with this program; if not, write to the Free Software 19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 20 | * MA 02110-1301, USA. 21 | */ 22 | 23 | #include "rtmouse.h" 24 | 25 | #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) 26 | static int mcp3204_remove(struct spi_device *spi); 27 | #else 28 | static void mcp3204_remove(struct spi_device *spi); 29 | #endif 30 | static int mcp3204_probe(struct spi_device *spi); 31 | 32 | /* 33 | * SPI device ID 34 | * used in mcp3204_driver 35 | */ 36 | static struct spi_device_id mcp3204_id[] = { 37 | {"mcp3204", 0}, 38 | {}, 39 | }; 40 | 41 | /* 42 | * SPI Info 43 | * used in mcp3204_probe(), mcp3204_init(), mcp3204_exit() 44 | * and mcp3204_get_value() 45 | */ 46 | struct spi_board_info mcp3204_info = { 47 | .modalias = "mcp3204", 48 | .max_speed_hz = 100000, 49 | .bus_num = 0, 50 | .chip_select = 0, 51 | .mode = SPI_MODE_3, 52 | }; 53 | 54 | /* 55 | * SPI Dirver Info 56 | * used in mcp3204_init() and mcp3204_exit() 57 | */ 58 | static struct spi_driver mcp3204_driver = { 59 | .driver = 60 | { 61 | .name = DEVNAME_SENSOR, 62 | .owner = THIS_MODULE, 63 | }, 64 | .id_table = mcp3204_id, 65 | .probe = mcp3204_probe, 66 | .remove = mcp3204_remove, 67 | }; 68 | 69 | /* -- Device Addition -- */ 70 | MODULE_DEVICE_TABLE(spi, mcp3204_id); 71 | 72 | /* 73 | * mcp3204_remove - remove function lined with spi_dirver 74 | * used in mcp3204_driver and mcp3204_exit() 75 | */ 76 | #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 18, 0) 77 | static int mcp3204_remove(struct spi_device *spi) 78 | { 79 | struct mcp3204_drvdata *data; 80 | /* get drvdata */ 81 | data = (struct mcp3204_drvdata *)spi_get_drvdata(spi); 82 | /* free kernel memory */ 83 | kfree(data); 84 | printk(KERN_INFO "%s: mcp3204 removed\n", DRIVER_NAME); 85 | return 0; 86 | } 87 | #else 88 | static void mcp3204_remove(struct spi_device *spi) 89 | { 90 | struct mcp3204_drvdata *data; 91 | /* get drvdata */ 92 | data = (struct mcp3204_drvdata *)spi_get_drvdata(spi); 93 | /* free kernel memory */ 94 | kfree(data); 95 | printk(KERN_INFO "%s: mcp3204 removed\n", DRIVER_NAME); 96 | } 97 | #endif 98 | 99 | /* 100 | * mcp3204_probe - probe function lined with spi_dirver 101 | * used in mcp3204_driver and __callback_find_mcp3204() 102 | */ 103 | static int mcp3204_probe(struct spi_device *spi) 104 | { 105 | struct mcp3204_drvdata *data; 106 | 107 | spi->max_speed_hz = mcp3204_info.max_speed_hz; 108 | spi->mode = mcp3204_info.mode; 109 | spi->bits_per_word = 8; 110 | 111 | if (spi_setup(spi)) { 112 | printk(KERN_ERR "%s:spi_setup failed!\n", __func__); 113 | return -ENODEV; 114 | } 115 | 116 | /* alloc kernel memory */ 117 | data = kzalloc(sizeof(struct mcp3204_drvdata), GFP_KERNEL); 118 | if (data == NULL) { 119 | printk(KERN_ERR "%s:kzalloc() failed!\n", __func__); 120 | return -ENODEV; 121 | } 122 | 123 | data->spi = spi; 124 | 125 | mutex_init(&data->lock); 126 | 127 | // memset(data->tx, 0, MCP320X_PACKET_SIZE); 128 | // memset(data->rx, 0, MCP320X_PACKET_SIZE); 129 | 130 | data->xfer.tx_buf = data->tx; 131 | data->xfer.rx_buf = data->rx; 132 | data->xfer.bits_per_word = 8; 133 | data->xfer.len = MCP320X_PACKET_SIZE; 134 | data->xfer.cs_change = 0; 135 | data->xfer.speed_hz = 100000; 136 | 137 | spi_message_init_with_transfers(&data->msg, &data->xfer, 1); 138 | 139 | /* set drvdata */ 140 | spi_set_drvdata(spi, data); 141 | 142 | printk(KERN_INFO "%s: mcp3204 probed", DRIVER_NAME); 143 | 144 | return 0; 145 | } 146 | 147 | /* 148 | * spi_remove_device - remove SPI device 149 | * called by mcp3204_init() and mcp3204_exit() 150 | */ 151 | static void spi_remove_device(struct spi_master *master, unsigned int cs) 152 | { 153 | struct device *dev; 154 | char str[128]; 155 | 156 | snprintf(str, sizeof(str), "%s.%u", dev_name(&master->dev), cs); 157 | 158 | dev = bus_find_device_by_name(&spi_bus_type, NULL, str); 159 | // ここを参考にspi_deviceを取得するプログラムを作成する 160 | if (dev) { 161 | device_del(dev); 162 | } 163 | } 164 | 165 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 166 | /* 167 | * spiをサーチする関数 168 | * used in mcp3204_init() 169 | */ 170 | static int __callback_find_mcp3204(struct device *dev, void *data) 171 | { 172 | printk(KERN_INFO " device_name: %s\n", dev->driver->name); 173 | if (mcp320x_dev == NULL && strcmp(dev->driver->name, "mcp320x") == 0) { 174 | mcp320x_dev = dev; 175 | mcp3204_probe(to_spi_device(dev)); 176 | } 177 | return 0; 178 | } 179 | #endif 180 | 181 | /* 182 | * mcp3204_init - initialize MCP3204 183 | * called by dev_init_module() 184 | */ 185 | int mcp3204_init(void) 186 | { 187 | 188 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 189 | bus_for_each_dev(&spi_bus_type, NULL, NULL, __callback_find_mcp3204); 190 | #else 191 | struct spi_master *master; 192 | struct spi_device *spi_device; 193 | 194 | spi_register_driver(&mcp3204_driver); 195 | 196 | mcp3204_info.bus_num = SPI_BUS_NUM; 197 | mcp3204_info.chip_select = SPI_CHIP_SELECT; 198 | 199 | master = spi_busnum_to_master(mcp3204_info.bus_num); 200 | 201 | if (!master) { 202 | printk(KERN_ERR "%s: spi_busnum_to_master returned NULL\n", 203 | __func__); 204 | spi_unregister_driver(&mcp3204_driver); 205 | return -ENODEV; 206 | } 207 | 208 | spi_remove_device(master, mcp3204_info.chip_select); 209 | 210 | spi_device = spi_new_device(master, &mcp3204_info); 211 | if (!spi_device) { 212 | printk(KERN_ERR "%s: spi_new_device returned NULL\n", __func__); 213 | spi_unregister_driver(&mcp3204_driver); 214 | return -ENODEV; 215 | } 216 | #endif 217 | 218 | return 0; 219 | } 220 | 221 | /* 222 | * mcp3204_exit - cleanup MCP3204 223 | * called by dev_cleanup_module() 224 | */ 225 | void mcp3204_exit(void) 226 | { 227 | 228 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 16, 0) 229 | printk(KERN_INFO " mcp3204_exit\n"); 230 | if (mcp320x_dev) { 231 | mcp3204_remove(to_spi_device(mcp320x_dev)); 232 | } 233 | #else 234 | struct spi_master *master; 235 | master = spi_busnum_to_master(mcp3204_info.bus_num); 236 | 237 | if (master) { 238 | spi_remove_device(master, mcp3204_info.chip_select); 239 | } else { 240 | printk(KERN_ERR "mcp3204 remove error\n"); 241 | } 242 | 243 | spi_unregister_driver(&mcp3204_driver); 244 | #endif 245 | } 246 | -------------------------------------------------------------------------------- /supplement/README.md: -------------------------------------------------------------------------------- 1 | This directory has been moved to [rt-net/RaspberryPiMouse_Hardware](https://github.com/rt-net/RaspberryPiMouse_Hardware). 2 | 3 | このディレクトリは[rt-net/RaspberryPiMouse_Hardware](https://github.com/rt-net/RaspberryPiMouse_Hardware)へ移行しました。 4 | -------------------------------------------------------------------------------- /utils/build_install.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu 3 | 4 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/../; pwd) 5 | 6 | if [ -e /usr/src/linux ]; then 7 | # build with linux headers installed from source 8 | if grep -q "Raspberry Pi 4" /proc/cpuinfo; then 9 | echo build_install_header_from_source_raspi4.bash 10 | $SRC_DIR/utils/build_install_header_from_source_raspi4.bash 11 | exit 0 12 | else 13 | echo build_install_header_from_source_raspi2.bash 14 | $SRC_DIR/utils/build_install_header_from_source_raspi2.bash 15 | exit 0 16 | fi 17 | elif [ "$(ls /usr/src/linux-* 2> /dev/null)" != '' ]; then 18 | # build with linux headers installed with apt 19 | if grep -q "Raspberry Pi 4" /proc/cpuinfo; then 20 | echo build_install_header_from_apt_raspi4.bash 21 | $SRC_DIR/utils/build_install_header_from_apt_raspi4.bash 22 | exit 0 23 | else 24 | echo build_install_header_from_apt_raspi2.bash 25 | $SRC_DIR/utils/build_install_header_from_apt_raspi2.bash 26 | exit 0 27 | fi 28 | else 29 | # Error 30 | bash -e $SRC_DIR/utils/print_env.bash "No kernel header files found." 31 | fi 32 | -------------------------------------------------------------------------------- /utils/build_install.raspbian.bash: -------------------------------------------------------------------------------- 1 | build_install_header_from_source_raspi2.bash -------------------------------------------------------------------------------- /utils/build_install.ubuntu14.bash: -------------------------------------------------------------------------------- 1 | build_install_header_from_apt_raspi2.bash -------------------------------------------------------------------------------- /utils/build_install_header_from_apt_raspi2.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/../; pwd) 4 | 5 | # check kernel headers 6 | [ ! -e /usr/src/linux-headers-$(uname -r) ] && { bash -e $SRC_DIR/utils/print_env.bash "No kernel header files found."; exit 1; } 7 | 8 | # build and install the driver 9 | cd $SRC_DIR/src/drivers/ 10 | rm Makefile 11 | ln -s Makefile.header_from_apt Makefile 12 | make clean 13 | make 14 | sudo insmod rtmouse.ko 15 | 16 | # initialize the driver 17 | sleep 1 18 | sudo chmod 666 /dev/rt* 19 | echo 0 > /dev/rtmotoren0 20 | -------------------------------------------------------------------------------- /utils/build_install_header_from_apt_raspi4.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/../; pwd) 4 | 5 | # check kernel headers 6 | [ ! -e /usr/src/linux-headers-$(uname -r) ] && { bash -e $SRC_DIR/utils/print_env.bash "No kernel header files found."; exit 1; } 7 | 8 | # build and install the driver 9 | cd $SRC_DIR/src/drivers/ 10 | rm Makefile 11 | ln -s Makefile.header_from_apt Makefile 12 | make clean 13 | # Update for Raspberry Pi 4 14 | sed -i -e "s/#define RASPBERRYPI 2/#define RASPBERRYPI 4/g" rtmouse.h 15 | make 16 | sudo insmod rtmouse.ko 17 | 18 | # initialize the driver 19 | sleep 1 20 | sudo chmod 666 /dev/rt* 21 | echo 0 > /dev/rtmotoren0 22 | -------------------------------------------------------------------------------- /utils/build_install_header_from_source_raspi2.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/../; pwd) 4 | 5 | # check kernel headers 6 | [ ! -e /usr/src/linux ] && { bash -e $SRC_DIR/utils/print_env.bash "No kernel header files found."; exit 1; } 7 | 8 | # build and install the driver 9 | cd $SRC_DIR/src/drivers/ 10 | rm Makefile 11 | ln -s Makefile.header_from_source Makefile 12 | make clean 13 | make 14 | sudo insmod rtmouse.ko 15 | 16 | # initialize the driver 17 | sleep 1 18 | sudo chmod 666 /dev/rt* 19 | echo 0 > /dev/rtmotoren0 20 | -------------------------------------------------------------------------------- /utils/build_install_header_from_source_raspi4.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash -eu 2 | 3 | SRC_DIR=$(cd $(dirname ${BASH_SOURCE:-$0})/../; pwd) 4 | 5 | # check kernel headers 6 | [ ! -e /usr/src/linux ] && { bash -e $SRC_DIR/utils/print_env.bash "No kernel header files found."; exit 1; } 7 | 8 | # build and install the driver 9 | cd $SRC_DIR/src/drivers/ 10 | rm Makefile 11 | ln -s Makefile.header_from_source Makefile 12 | make clean 13 | # Update for Raspberry Pi 4 14 | sed -i -e "s/#define RASPBERRYPI 2/#define RASPBERRYPI 4/g" rtmouse.h 15 | make 16 | sudo insmod rtmouse.ko 17 | 18 | # initialize the driver 19 | sleep 1 20 | sudo chmod 666 /dev/rt* 21 | echo 0 > /dev/rtmotoren0 22 | -------------------------------------------------------------------------------- /utils/print_env.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -u 3 | set +exv 4 | 5 | echo "===================" 6 | echo "ERROR: $@" 7 | echo "If you need someone's support, you should share this information." 8 | uname -a 9 | lsb_release -a || cat /etc/lsb-release 10 | ls /usr/src/linux* 11 | echo "===================" 12 | -------------------------------------------------------------------------------- /utils/set_configs.bash: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -eu 3 | 4 | # settings comment 5 | SETTING_COMMENT='# Raspberry Pi Mouse V3 settings' 6 | 7 | # OS architecture (32-bit or 64-bit) 8 | ARCHITECTURE=$(getconf LONG_BIT) 9 | 10 | # dtoverlay setting 11 | DTOVERLAY='dtoverlay=anyspi:spi0-0,dev="microchip,mcp3204",speed=1000000' 12 | 13 | # i2c_baudrate-setting 14 | DTPARAM='dtparam=i2c_baudrate=62500' 15 | 16 | # config-file PATH 17 | CONFIG_FILE='/boot/firmware/config.txt' 18 | 19 | # compare kernel versions as integers for accurate version comparison (excluding minor versions). 20 | GET_KERNEL_VERSION_INT() { 21 | # 0-padding is used to avoid minor versions being compared by their first digit. 22 | echo "$1" | awk -F. '{ printf "%d%02d", $1, $2 }' 23 | } 24 | 25 | # kernel version 26 | KERNEL_VERSION=$(uname -r | cut -d'-' -f1) 27 | KERNEL_VERSION_INT=$(GET_KERNEL_VERSION_INT "$KERNEL_VERSION") 28 | 29 | # add "Raspberry Pi Mouse v3" settings 30 | if ! grep -qxF "$SETTING_COMMENT" "$CONFIG_FILE"; then 31 | echo "$SETTING_COMMENT" | sudo tee -a "$CONFIG_FILE" > /dev/null 32 | fi 33 | 34 | # check if the OS is running in 32-bit mode 35 | if [[ "$ARCHITECTURE" == "32" ]]; then 36 | if ! grep -qxF "arm_64bit=0" "$CONFIG_FILE"; then 37 | echo "arm_64bit=0" | sudo tee -a "$CONFIG_FILE" 38 | echo "Add \"arm_64bit=0\" > $CONFIG_FILE" 39 | fi 40 | elif [[ "$ARCHITECTURE" == "64" ]]; then 41 | # remove arm_64bit=0 if present in a 64-bit environment 42 | if grep -qxF "arm_64bit=0" "$CONFIG_FILE"; then 43 | sudo sed -i '/arm_64bit=0/d' "$CONFIG_FILE" 44 | echo "Removed \"arm_64bit=0\" from $CONFIG_FILE" 45 | fi 46 | fi 47 | 48 | # add dtparam-setting for "/boot/firmware/config.txt" 49 | if ! grep -qxF "$DTPARAM" "$CONFIG_FILE"; then 50 | echo "$DTPARAM" | sudo tee -a "$CONFIG_FILE" > /dev/null 51 | echo "Add \"$DTPARAM\" > $CONFIG_FILE" 52 | fi 53 | 54 | # use device-tree-overlay when the kernel is 5.16 or higher 55 | if (( KERNEL_VERSION_INT >= $(GET_KERNEL_VERSION_INT 5.16) )); then 56 | # add dtoverlay-setting for "/boot/firmware/config.txt" 57 | if ! grep -qxF "$DTOVERLAY" "$CONFIG_FILE"; then 58 | echo "$DTOVERLAY" | sudo tee -a "$CONFIG_FILE" > /dev/null 59 | echo "Add \"$DTOVERLAY\" > $CONFIG_FILE" 60 | fi 61 | else 62 | # remove dtoverlay-setting if kernel is less than 5.16 63 | if grep -qxF "$DTOVERLAY" "$CONFIG_FILE"; then 64 | sudo sed -i "/$DTOVERLAY/d" "$CONFIG_FILE" 65 | echo "Removed \"$DTOVERLAY\" from $CONFIG_FILE" 66 | fi 67 | fi 68 | 69 | # replace "dtparam=i2c_arm=off" with "dtparam=i2c_arm=on" 70 | if grep -qxF 'dtparam=i2c_arm=off' "$CONFIG_FILE"; then 71 | sudo sed -i 's/dtparam=i2c_arm=off/dtparam=i2c_arm=on/' "$CONFIG_FILE" 72 | echo "Changed \"dtparam=i2c_arm=off\" to \"dtparam=i2c_arm=on\" in $CONFIG_FILE" 73 | fi 74 | 75 | # replace "dtparam=spi=off" with "dtparam=spi=on" 76 | if grep -qxF 'dtparam=spi=off' "$CONFIG_FILE"; then 77 | sudo sed -i 's/dtparam=spi=off/dtparam=spi=on/' "$CONFIG_FILE" 78 | echo "Changed \"dtparam=spi=off\" to \"dtparam=spi=on\" in $CONFIG_FILE" 79 | fi 80 | 81 | # uncomment "dtparam=i2c_arm=on" if it is commented 82 | if grep -qxF '#dtparam=i2c_arm=on' "$CONFIG_FILE"; then 83 | sudo sed -i 's/#dtparam=i2c_arm=on/dtparam=i2c_arm=on/' "$CONFIG_FILE" 84 | echo "Uncommented \"dtparam=i2c_arm=on\" in $CONFIG_FILE" 85 | fi 86 | 87 | # uncomment "dtparam=spi=on" if it is commented 88 | if grep -qxF '#dtparam=spi=on' "$CONFIG_FILE"; then 89 | sudo sed -i 's/#dtparam=spi=on/dtparam=spi=on/' "$CONFIG_FILE" 90 | echo "Uncommented \"dtparam=spi=on\" in $CONFIG_FILE" 91 | fi 92 | --------------------------------------------------------------------------------