1/* 2 * Copyright 2009-2011, Michael Lotz, mmlr@mlotz.ch. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7#include <stdlib.h> 8#include <ring_buffer.h> 9#include <kernel.h> 10 11#include "Driver.h" 12#include "HIDCollection.h" 13#include "HIDDevice.h" 14#include "HIDReport.h" 15#include "ProtocolHandler.h" 16 17// includes for the different protocol handlers 18#include "JoystickProtocolHandler.h" 19#include "KeyboardProtocolHandler.h" 20#include "MouseProtocolHandler.h" 21#include "TabletProtocolHandler.h" 22 23 24ProtocolHandler::ProtocolHandler(HIDDevice *device, const char *basePath, 25 size_t ringBufferSize) 26 : fStatus(B_NO_INIT), 27 fDevice(device), 28 fBasePath(basePath), 29 fPublishPath(NULL), 30 fRingBuffer(NULL), 31 fNextHandler(NULL) 32{ 33 if (ringBufferSize > 0) { 34 fRingBuffer = create_ring_buffer(ringBufferSize); 35 if (fRingBuffer == NULL) { 36 TRACE_ALWAYS("failed to create requested ring buffer\n"); 37 fStatus = B_NO_MEMORY; 38 return; 39 } 40 } 41 42 fStatus = B_OK; 43} 44 45 46ProtocolHandler::~ProtocolHandler() 47{ 48 if (fRingBuffer) { 49 delete_ring_buffer(fRingBuffer); 50 fRingBuffer = NULL; 51 } 52 53 free(fPublishPath); 54} 55 56 57void 58ProtocolHandler::SetPublishPath(char *publishPath) 59{ 60 free(fPublishPath); 61 fPublishPath = publishPath; 62} 63 64 65void 66ProtocolHandler::AddHandlers(HIDDevice &device, ProtocolHandler *&handlerList, 67 uint32 &handlerCount) 68{ 69 TRACE("adding protocol handlers\n"); 70 71 HIDParser &parser = device.Parser(); 72 HIDCollection *rootCollection = parser.RootCollection(); 73 if (rootCollection == NULL) 74 return; 75 76 uint32 appCollectionCount = rootCollection->CountChildrenFlat( 77 COLLECTION_APPLICATION); 78 TRACE("root collection holds %" B_PRIu32 " application collection%s\n", 79 appCollectionCount, appCollectionCount != 1 ? "s" : ""); 80 81 for (uint32 i = 0; i < appCollectionCount; i++) { 82 HIDCollection *collection = rootCollection->ChildAtFlat( 83 COLLECTION_APPLICATION, i); 84 if (collection == NULL) 85 continue; 86 87 TRACE("collection usage page %u usage id %u\n", 88 collection->UsagePage(), collection->UsageID()); 89 90 // NOTE: The driver publishes devices for all added handlers. 91 92 // TODO: How does this work if a device is not a compound device 93 // like a keyboard with built-in touchpad, but allows multiple 94 // alternative configurations like a tablet that works as either 95 // regular (relative) mouse, or (absolute) tablet? 96 KeyboardProtocolHandler::AddHandlers(device, *collection, handlerList); 97 JoystickProtocolHandler::AddHandlers(device, *collection, handlerList); 98 MouseProtocolHandler::AddHandlers(device, *collection, handlerList); 99 TabletProtocolHandler::AddHandlers(device, *collection, handlerList); 100 } 101 102 handlerCount = 0; 103 ProtocolHandler *handler = handlerList; 104 while (handler != NULL) { 105 handler = handler->NextHandler(); 106 handlerCount++; 107 } 108 109 if (handlerCount == 0) { 110 TRACE_ALWAYS("no handlers for hid device\n"); 111 return; 112 } 113 114 TRACE("added %" B_PRId32 " handlers for hid device\n", handlerCount); 115} 116 117 118status_t 119ProtocolHandler::Open(uint32 flags, uint32 *cookie) 120{ 121 return fDevice->Open(this, flags); 122} 123 124 125status_t 126ProtocolHandler::Close(uint32 *cookie) 127{ 128 *cookie |= PROTOCOL_HANDLER_COOKIE_FLAG_CLOSED; 129 // This lets the handlers know that this user is gone. 130 131 return fDevice->Close(this); 132} 133 134 135status_t 136ProtocolHandler::Read(uint32 *cookie, off_t position, void *buffer, 137 size_t *numBytes) 138{ 139 TRACE_ALWAYS("unhandled read on protocol handler\n"); 140 *numBytes = 0; 141 return B_ERROR; 142} 143 144 145status_t 146ProtocolHandler::Write(uint32 *cookie, off_t position, const void *buffer, 147 size_t *numBytes) 148{ 149 TRACE_ALWAYS("unhandled write on protocol handler\n"); 150 *numBytes = 0; 151 return B_ERROR; 152} 153 154 155status_t 156ProtocolHandler::Control(uint32 *cookie, uint32 op, void *buffer, size_t length) 157{ 158 TRACE_ALWAYS("unhandled control on protocol handler\n"); 159 return B_ERROR; 160} 161 162 163int32 164ProtocolHandler::RingBufferReadable() 165{ 166 return ring_buffer_readable(fRingBuffer); 167} 168 169 170status_t 171ProtocolHandler::RingBufferRead(void *buffer, size_t length) 172{ 173 ring_buffer_user_read(fRingBuffer, (uint8 *)buffer, length); 174 return B_OK; 175} 176 177 178status_t 179ProtocolHandler::RingBufferWrite(const void *buffer, size_t length) 180{ 181 ring_buffer_write(fRingBuffer, (const uint8 *)buffer, length); 182 return B_OK; 183} 184 185 186void 187ProtocolHandler::SetNextHandler(ProtocolHandler *nextHandler) 188{ 189 fNextHandler = nextHandler; 190} 191 192status_t 193ProtocolHandler::IOGetDeviceName(const char *name, void *buffer, size_t length) 194{ 195 196 if (!IS_USER_ADDRESS(buffer)) 197 return B_BAD_ADDRESS; 198 199 if (user_strlcpy((char *)buffer, name, length) > 0) 200 return B_OK; 201 202 return B_ERROR; 203} 204