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