xref: /haiku/src/add-ons/kernel/drivers/input/hid_shared/ProtocolHandler.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
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