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