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