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