/* * Copyright 2005-2007, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Author(s): * Ingo Weinhold * * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. * Distributed under the terms of the NewOS License. */ #include #include #include #include #include #define DEVICE_NAME "dprintf" int32 api_version = B_CUR_DRIVER_API_VERSION; static status_t dprintf_open(const char *name, uint32 flags, void **cookie) { *cookie = NULL; return B_OK; } static status_t dprintf_close(void *cookie) { return B_OK; } static status_t dprintf_freecookie(void *cookie) { return B_OK; } static status_t dprintf_ioctl(void *cookie, uint32 op, void *buffer, size_t length) { if (op == TCGETA) { // let isatty() think we are a terminal // (this lets libroot use unbuffered I/O) return B_OK; } return EPERM; } static status_t dprintf_read(void *cookie, off_t pos, void *buffer, size_t *length) { *length = 0; return B_OK; } static status_t dprintf_write(void *cookie, off_t pos, const void *buffer, size_t *_length) { const char *str = (const char*)buffer; int bytesLeft = *_length; while (bytesLeft > 0) { ssize_t size = user_strlcpy(NULL, str, 0); // there's no user_strnlen() if (size < 0) return 0; int chunkSize = min_c(bytesLeft, (int)size); // int chunkSize = strnlen(str, bytesLeft); if (chunkSize == 0) { // null bytes -- skip str++; bytesLeft--; continue; } if (chunkSize == bytesLeft) { // no null-byte in the remainder of the buffer // we need to copy to a local buffer and null-terminate while (bytesLeft > 0) { chunkSize = bytesLeft; char localBuffer[512]; if (bytesLeft > (int)sizeof(localBuffer) - 1) chunkSize = (int)sizeof(localBuffer) - 1; if (user_memcpy(localBuffer, str, chunkSize) < B_OK) return B_BAD_ADDRESS; localBuffer[chunkSize] = '\0'; debug_puts(localBuffer, chunkSize); str += chunkSize; bytesLeft -= chunkSize; } } else { // null-terminated chunk -- just write it debug_puts(str, chunkSize); str += chunkSize + 1; bytesLeft -= chunkSize + 1; } } return B_OK; } // #pragma mark - status_t init_hardware(void) { return B_OK; } const char ** publish_devices(void) { static const char *devices[] = { DEVICE_NAME, NULL }; return devices; } device_hooks * find_device(const char *name) { static device_hooks hooks = { &dprintf_open, &dprintf_close, &dprintf_freecookie, &dprintf_ioctl, &dprintf_read, &dprintf_write, /* Leave select/deselect/readv/writev undefined. The kernel will * use its own default implementation. The basic hooks above this * line MUST be defined, however. */ NULL, NULL, NULL, NULL }; if (!strcmp(name, DEVICE_NAME)) return &hooks; return NULL; } status_t init_driver(void) { return B_OK; } void uninit_driver(void) { }