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 24 int32 api_version = B_CUR_DRIVER_API_VERSION; 25 26 27 static status_t 28 dprintf_open(const char *name, uint32 flags, void **cookie) 29 { 30 *cookie = NULL; 31 return B_OK; 32 } 33 34 35 static status_t 36 dprintf_close(void *cookie) 37 { 38 return B_OK; 39 } 40 41 42 static status_t 43 dprintf_freecookie(void *cookie) 44 { 45 return B_OK; 46 } 47 48 49 static status_t 50 dprintf_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 62 static status_t 63 dprintf_read(void *cookie, off_t pos, void *buffer, size_t *length) 64 { 65 *length = 0; 66 return B_OK; 67 } 68 69 70 static status_t 71 dprintf_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 125 status_t 126 init_hardware(void) 127 { 128 return B_OK; 129 } 130 131 132 const char ** 133 publish_devices(void) 134 { 135 static const char *devices[] = { 136 DEVICE_NAME, 137 NULL 138 }; 139 140 return devices; 141 } 142 143 144 device_hooks * 145 find_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 170 status_t 171 init_driver(void) 172 { 173 return B_OK; 174 } 175 176 177 void 178 uninit_driver(void) 179 { 180 } 181 182