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 24 ProtocolHandler::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 46 ProtocolHandler::~ProtocolHandler() 47 { 48 if (fRingBuffer) { 49 delete_ring_buffer(fRingBuffer); 50 fRingBuffer = NULL; 51 } 52 53 free(fPublishPath); 54 } 55 56 57 void 58 ProtocolHandler::SetPublishPath(char *publishPath) 59 { 60 free(fPublishPath); 61 fPublishPath = publishPath; 62 } 63 64 65 void 66 ProtocolHandler::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 118 status_t 119 ProtocolHandler::Open(uint32 flags, uint32 *cookie) 120 { 121 return fDevice->Open(this, flags); 122 } 123 124 125 status_t 126 ProtocolHandler::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 135 status_t 136 ProtocolHandler::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 145 status_t 146 ProtocolHandler::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 155 status_t 156 ProtocolHandler::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 163 int32 164 ProtocolHandler::RingBufferReadable() 165 { 166 return ring_buffer_readable(fRingBuffer); 167 } 168 169 170 status_t 171 ProtocolHandler::RingBufferRead(void *buffer, size_t length) 172 { 173 ring_buffer_user_read(fRingBuffer, (uint8 *)buffer, length); 174 return B_OK; 175 } 176 177 178 status_t 179 ProtocolHandler::RingBufferWrite(const void *buffer, size_t length) 180 { 181 ring_buffer_write(fRingBuffer, (const uint8 *)buffer, length); 182 return B_OK; 183 } 184 185 186 void 187 ProtocolHandler::SetNextHandler(ProtocolHandler *nextHandler) 188 { 189 fNextHandler = nextHandler; 190 } 191 192 status_t 193 ProtocolHandler::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