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
ProtocolHandler(HIDDevice * device,const char * basePath,size_t ringBufferSize)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
~ProtocolHandler()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
SetPublishPath(char * publishPath)58 ProtocolHandler::SetPublishPath(char *publishPath)
59 {
60 free(fPublishPath);
61 fPublishPath = publishPath;
62 }
63
64
65 void
AddHandlers(HIDDevice & device,ProtocolHandler * & handlerList,uint32 & handlerCount)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
Open(uint32 flags,uint32 * cookie)119 ProtocolHandler::Open(uint32 flags, uint32 *cookie)
120 {
121 return fDevice->Open(this, flags);
122 }
123
124
125 status_t
Close(uint32 * cookie)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
Read(uint32 * cookie,off_t position,void * buffer,size_t * numBytes)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
Write(uint32 * cookie,off_t position,const void * buffer,size_t * numBytes)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
Control(uint32 * cookie,uint32 op,void * buffer,size_t length)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
RingBufferReadable()164 ProtocolHandler::RingBufferReadable()
165 {
166 return ring_buffer_readable(fRingBuffer);
167 }
168
169
170 status_t
RingBufferRead(void * buffer,size_t length)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
RingBufferWrite(const void * buffer,size_t length)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
SetNextHandler(ProtocolHandler * nextHandler)187 ProtocolHandler::SetNextHandler(ProtocolHandler *nextHandler)
188 {
189 fNextHandler = nextHandler;
190 }
191
192 status_t
IOGetDeviceName(const char * name,void * buffer,size_t length)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