xref: /haiku/src/add-ons/kernel/drivers/common/dprintf.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2005-2007, Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Author(s):
6  *   Ingo Weinhold <bonefish@users.sourceforge.net>
7  *
8  * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
9  * Distributed under the terms of the NewOS License.
10  */
11 
12 
13 #include <debug.h>
14 #include <kernel.h>
15 
16 #include <Drivers.h>
17 #include <KernelExport.h>
18 
19 #include <string.h>
20 #include <termios.h>
21 
22 
23 #define DEVICE_NAME "dprintf"
24 
25 int32 api_version = B_CUR_DRIVER_API_VERSION;
26 
27 
28 static status_t
29 dprintf_open(const char *name, uint32 flags, void **cookie)
30 {
31 	*cookie = NULL;
32 	return B_OK;
33 }
34 
35 
36 static status_t
37 dprintf_close(void *cookie)
38 {
39 	return B_OK;
40 }
41 
42 
43 static status_t
44 dprintf_freecookie(void *cookie)
45 {
46 	return B_OK;
47 }
48 
49 
50 static status_t
51 dprintf_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
52 {
53 	if (op == TCGETA) {
54 		// let isatty() think we are a terminal
55 		// (this lets libroot use unbuffered I/O)
56 		return B_OK;
57 	}
58 
59 	return EPERM;
60 }
61 
62 
63 static status_t
64 dprintf_read(void *cookie, off_t pos, void *buffer, size_t *length)
65 {
66 	*length = 0;
67 	return B_OK;
68 }
69 
70 
71 static status_t
72 dprintf_write(void *cookie, off_t pos, const void *buffer, size_t *_length)
73 {
74 	if (!IS_USER_ADDRESS(buffer))
75 		return B_BAD_ADDRESS;
76 	const char *str = (const char*)buffer;
77 
78 	int bytesLeft = *_length;
79 	while (bytesLeft > 0) {
80 		ssize_t size = user_strlcpy(NULL, str, 0);
81 			// there's no user_strnlen()
82 		if (size < 0)
83 			return 0;
84 		int chunkSize = min_c(bytesLeft, (int)size);
85 		// int chunkSize = strnlen(str, bytesLeft);
86 
87 		if (chunkSize == 0) {
88 			// null bytes -- skip
89 			str++;
90 			bytesLeft--;
91 			continue;
92 		}
93 
94 		if (chunkSize == bytesLeft) {
95 			// no null-byte in the remainder of the buffer
96 			// we need to copy to a local buffer and null-terminate
97 			while (bytesLeft > 0) {
98 				chunkSize = bytesLeft;
99 
100 				char localBuffer[512];
101 				if (bytesLeft > (int)sizeof(localBuffer) - 1)
102 					chunkSize = (int)sizeof(localBuffer) - 1;
103 				user_memcpy(localBuffer, str, chunkSize);
104 				localBuffer[chunkSize] = '\0';
105 
106 				debug_puts(localBuffer, chunkSize);
107 
108 				str += chunkSize;
109 				bytesLeft -= chunkSize;
110 			}
111 		} else {
112 			// null-terminated chunk -- just write it
113 			debug_puts(str, chunkSize);
114 
115 			str += chunkSize + 1;
116 			bytesLeft -= chunkSize + 1;
117 		}
118 	}
119 
120 	return B_OK;
121 }
122 
123 
124 //	#pragma mark -
125 
126 
127 status_t
128 init_hardware(void)
129 {
130 	return B_OK;
131 }
132 
133 
134 const char **
135 publish_devices(void)
136 {
137 	static const char *devices[] = {
138 		DEVICE_NAME,
139 		NULL
140 	};
141 
142 	return devices;
143 }
144 
145 
146 device_hooks *
147 find_device(const char *name)
148 {
149 	static device_hooks hooks = {
150 		&dprintf_open,
151 		&dprintf_close,
152 		&dprintf_freecookie,
153 		&dprintf_ioctl,
154 		&dprintf_read,
155 		&dprintf_write,
156 		/* Leave select/deselect/readv/writev undefined. The kernel will
157 		 * use its own default implementation. The basic hooks above this
158 		 * line MUST be defined, however. */
159 		NULL,
160 		NULL,
161 		NULL,
162 		NULL
163 	};
164 
165 	if (!strcmp(name, DEVICE_NAME))
166 		return &hooks;
167 
168 	return NULL;
169 }
170 
171 
172 status_t
173 init_driver(void)
174 {
175 	return B_OK;
176 }
177 
178 
179 void
180 uninit_driver(void)
181 {
182 }
183 
184