Added doxygen style documentation to devmem2 module
[allwinner_tvout_manipulator.git] / src / devmem2.c
1 ///////////////////////////////////////////////////////////////////////////
2 // Workfile: devmem2.c (Implementation)
3 // Author: Jan-Derk Bakker, Daniel Giritzer
4 // Date: 2017-06-02
5 // Description: Simple module to read/write from/to any location in memory.
6 // Remarks: assumes a 4k page size and that sizeof(unsigned long) == 4
7 // Revision: 1.2
8 // Copyright (C) 2000, Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
9 // Copyright (C) 2017, Daniel Giritzer (giri@nwrk.biz)
10 ///////////////////////////////////////////////////////////////////////////
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <string.h>
16 #include <errno.h>
17 #include <signal.h>
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <termios.h>
21 #include <sys/types.h>
22 #include <sys/mman.h>
23
24 #include "devmem2.h"
25
26 #define MAP_SIZE 4096UL
27 #define MAP_MASK (MAP_SIZE - 1)
28
29
30 /////////////////////////////////////////////////
31 /// \brief This function is called by the module
32 ///        if an error occurs.
33 ///
34 /// \param char* Custom error Message.
35 /////////////////////////////////////////////////
36 static void ERROR(char* custom)
37 {
38     //print custom error message
39     fprintf(stderr, "Error: %s \n", custom);
40
41     //print further information
42     fprintf(stderr, "Info: %d, %s\n",
43             errno, strerror(errno));
44 }
45
46 /////////////////////////////////////////////////
47 /// \brief This function allows writing to memory
48 ///        on the specified address.
49 ///
50 /// \param char* Address to write to
51 /// \param char* Value to write
52 /// \param int Access type, should be 'w' (word),
53 ///        'h' (halfword), 'b'(byte)
54 /////////////////////////////////////////////////
55 int writemem(char* address, char* value, int access_type)
56 {
57     int fd;
58     void *map_base = 0;
59     void *virt_addr = 0;
60     unsigned long writeval = 0;
61
62     off_t target = strtoul(address, 0, 0);
63
64
65     if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
66     {
67         ERROR("Opening /dev/mem/ failed!");
68         return EXIT_FAILURE;
69     };
70
71     // Map one page
72     map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
73
74     if(map_base == (void *) -1)
75     {
76         ERROR("Mapping Memory Page Failed!");
77         return EXIT_FAILURE;
78     }
79
80
81     writeval = strtoul(value, 0, 0);
82     switch(access_type)
83     {
84     case 'b':
85         *((unsigned char *) virt_addr) = writeval;
86         break;
87     case 'h':
88         *((unsigned short *) virt_addr) = writeval;
89         break;
90     case 'w':
91         *((unsigned long *) virt_addr) = writeval;
92         break;
93     default:
94         ERROR("Wrong access_type set!");
95         break;
96     }
97
98
99     if(munmap(map_base, MAP_SIZE) == -1)
100     {
101         ERROR("Unmapping Memory Page Failed!");
102         return EXIT_FAILURE;
103     }
104
105     close(fd);
106     return EXIT_SUCCESS;
107 }
108
109 /////////////////////////////////////////////////
110 /// \brief This function allows reading the memory
111 ///        on the specified address.
112 ///
113 /// \param char* Address to read from
114 /// \param int Access type, should be 'w' (word),
115 ///        'h' (halfword), 'b'(byte)
116 /// \param unsigned long* pointer result variable
117 /////////////////////////////////////////////////
118 int readmem(char* address, int access_type, unsigned long *result)
119 {
120     int fd;
121     void *map_base, *virt_addr;
122     off_t target;
123     unsigned long read_result = 0;
124
125     target = strtoul(address, 0, 0);
126
127     if(result == NULL)
128     {
129         //Print error on failure
130         ERROR("Result Parameter is a nullpointer!");
131         return EXIT_FAILURE;
132     }
133
134
135     // Try to open /dev/mem
136     if((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1)
137     {
138         //Print error on failure
139         ERROR("Opening /dev/mem/ failed!");
140         return EXIT_FAILURE;
141     };
142
143     // Map one page
144     map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, target & ~MAP_MASK);
145
146     // Check if mapping was successful
147     if(map_base == (void *) -1)
148     {
149         ERROR("Mapping Memory Page Failed!");
150         return EXIT_FAILURE;
151     }
152
153     virt_addr = map_base + (target & MAP_MASK);
154     switch(access_type)
155     {
156     case 'b':
157         read_result = *((unsigned char *) virt_addr);
158         break;
159     case 'h':
160         read_result = *((unsigned short *) virt_addr);
161         break;
162     case 'w':
163         read_result = *((unsigned long *) virt_addr);
164         break;
165     default:
166         ERROR("Wrong access_type set!");
167         break;
168     }
169
170     if(munmap(map_base, MAP_SIZE) == -1)
171     {
172         ERROR("Unmapping Memory Page Failed!");
173         return EXIT_FAILURE;
174     }
175
176     *result = read_result;
177
178     close(fd);
179     return EXIT_SUCCESS;
180 }
181