]> git.gir.st - tmk_keyboard.git/blob - tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c
Merge commit 'f6d56675f9f981c5464f0ca7a1fbb0162154e8c5'
[tmk_keyboard.git] / tmk_core / protocol / lufa / LUFA-git / LUFA / Drivers / USB / Class / Host / PrinterClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2014.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2014 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11
12 Permission to use, copy, modify, distribute, and sell this
13 software and its documentation for any purpose is hereby granted
14 without fee, provided that the above copyright notice appear in
15 all copies and that both that the copyright notice and this
16 permission notice and warranty disclaimer appear in supporting
17 documentation, and that the name of the author not be used in
18 advertising or publicity pertaining to distribution of the
19 software without specific, written prior permission.
20
21 The author disclaims all warranties with regard to this
22 software, including all implied warranties of merchantability
23 and fitness. In no event shall the author be liable for any
24 special, indirect or consequential damages or any damages
25 whatsoever resulting from loss of use, data or profits, whether
26 in an action of contract, negligence or other tortious action,
27 arising out of or in connection with the use or performance of
28 this software.
29 */
30
31 #define __INCLUDE_FROM_USB_DRIVER
32 #include "../../Core/USBMode.h"
33
34 #if defined(USB_CAN_BE_HOST)
35
36 #define __INCLUDE_FROM_PRINTER_DRIVER
37 #define __INCLUDE_FROM_PRINTER_HOST_C
38 #include "PrinterClassHost.h"
39
40 uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
41 uint16_t ConfigDescriptorSize,
42 void* ConfigDescriptorData)
43 {
44 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
45 USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
46 USB_Descriptor_Interface_t* PrinterInterface = NULL;
47
48 memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
49
50 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
51 return PRNT_ENUMERROR_InvalidConfigDescriptor;
52
53 while (!(DataINEndpoint) || !(DataOUTEndpoint))
54 {
55 if (!(PrinterInterface) ||
56 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
57 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
58 {
59 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
60 DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
61 {
62 return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
63 }
64
65 PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
66
67 DataINEndpoint = NULL;
68 DataOUTEndpoint = NULL;
69
70 continue;
71 }
72
73 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
74
75 if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
76 DataINEndpoint = EndpointData;
77 else
78 DataOUTEndpoint = EndpointData;
79 }
80
81 PRNTInterfaceInfo->Config.DataINPipe.Size = le16_to_cpu(DataINEndpoint->EndpointSize);
82 PRNTInterfaceInfo->Config.DataINPipe.EndpointAddress = DataINEndpoint->EndpointAddress;
83 PRNTInterfaceInfo->Config.DataINPipe.Type = EP_TYPE_BULK;
84
85 PRNTInterfaceInfo->Config.DataOUTPipe.Size = le16_to_cpu(DataOUTEndpoint->EndpointSize);
86 PRNTInterfaceInfo->Config.DataOUTPipe.EndpointAddress = DataOUTEndpoint->EndpointAddress;
87 PRNTInterfaceInfo->Config.DataOUTPipe.Type = EP_TYPE_BULK;
88
89 if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataINPipe, 1)))
90 return PRNT_ENUMERROR_PipeConfigurationFailed;
91
92 if (!(Pipe_ConfigurePipeTable(&PRNTInterfaceInfo->Config.DataOUTPipe, 1)))
93 return PRNT_ENUMERROR_PipeConfigurationFailed;
94
95 PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
96 PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
97 PRNTInterfaceInfo->State.IsActive = true;
98
99 return PRNT_ENUMERROR_NoError;
100 }
101
102 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor)
103 {
104 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
105
106 if (Header->Type == DTYPE_Interface)
107 {
108 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
109
110 if ((Interface->Class == PRNT_CSCP_PrinterClass) &&
111 (Interface->SubClass == PRNT_CSCP_PrinterSubclass) &&
112 (Interface->Protocol == PRNT_CSCP_BidirectionalProtocol))
113 {
114 return DESCRIPTOR_SEARCH_Found;
115 }
116 }
117
118 return DESCRIPTOR_SEARCH_NotFound;
119 }
120
121 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
122 {
123 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
124
125 if (Header->Type == DTYPE_Endpoint)
126 {
127 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
128
129 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
130
131 if (EndpointType == EP_TYPE_BULK)
132 return DESCRIPTOR_SEARCH_Found;
133 }
134 else if (Header->Type == DTYPE_Interface)
135 {
136 return DESCRIPTOR_SEARCH_Fail;
137 }
138
139 return DESCRIPTOR_SEARCH_NotFound;
140 }
141
142 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
143 {
144 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
145 return;
146
147 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
148 PRNT_Host_Flush(PRNTInterfaceInfo);
149 #endif
150 }
151
152 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
153 {
154 if (PRNTInterfaceInfo->State.AlternateSetting)
155 {
156 uint8_t ErrorCode;
157
158 if ((ErrorCode = USB_Host_SetInterfaceAltSetting(PRNTInterfaceInfo->State.InterfaceNumber,
159 PRNTInterfaceInfo->State.AlternateSetting)) != HOST_SENDCONTROL_Successful)
160 {
161 return ErrorCode;
162 }
163 }
164
165 return HOST_SENDCONTROL_Successful;
166 }
167
168 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
169 uint8_t* const PortStatus)
170 {
171 USB_ControlRequest = (USB_Request_Header_t)
172 {
173 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
174 .bRequest = PRNT_REQ_GetPortStatus,
175 .wValue = 0,
176 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
177 .wLength = sizeof(uint8_t),
178 };
179
180 Pipe_SelectPipe(PIPE_CONTROLPIPE);
181 return USB_Host_SendControlRequest(PortStatus);
182 }
183
184 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
185 {
186 USB_ControlRequest = (USB_Request_Header_t)
187 {
188 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
189 .bRequest = PRNT_REQ_SoftReset,
190 .wValue = 0,
191 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
192 .wLength = 0,
193 };
194
195 Pipe_SelectPipe(PIPE_CONTROLPIPE);
196 return USB_Host_SendControlRequest(NULL);
197 }
198
199 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
200 {
201 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
202 return PIPE_READYWAIT_DeviceDisconnected;
203
204 uint8_t ErrorCode;
205
206 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
207 Pipe_Unfreeze();
208
209 if (!(Pipe_BytesInPipe()))
210 return PIPE_READYWAIT_NoError;
211
212 bool BankFull = !(Pipe_IsReadWriteAllowed());
213
214 Pipe_ClearOUT();
215
216 if (BankFull)
217 {
218 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
219 return ErrorCode;
220
221 Pipe_ClearOUT();
222 }
223
224 Pipe_Freeze();
225
226 return PIPE_READYWAIT_NoError;
227 }
228
229 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
230 const uint8_t Data)
231 {
232 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
233 return PIPE_READYWAIT_DeviceDisconnected;
234
235 uint8_t ErrorCode;
236
237 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
238 Pipe_Unfreeze();
239
240 if (!(Pipe_IsReadWriteAllowed()))
241 {
242 Pipe_ClearOUT();
243
244 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
245 return ErrorCode;
246 }
247
248 Pipe_Write_8(Data);
249 Pipe_Freeze();
250
251 return PIPE_READYWAIT_NoError;
252 }
253
254 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
255 const char* const String)
256 {
257 uint8_t ErrorCode;
258
259 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
260 return PIPE_RWSTREAM_DeviceDisconnected;
261
262 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
263 Pipe_Unfreeze();
264
265 if ((ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL)) != PIPE_RWSTREAM_NoError)
266 return ErrorCode;
267
268 Pipe_ClearOUT();
269
270 ErrorCode = Pipe_WaitUntilReady();
271
272 Pipe_Freeze();
273
274 return ErrorCode;
275 }
276
277 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
278 const void* Buffer,
279 const uint16_t Length)
280 {
281 uint8_t ErrorCode;
282
283 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
284 return PIPE_RWSTREAM_DeviceDisconnected;
285
286 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipe.Address);
287 Pipe_Unfreeze();
288
289 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL)) != PIPE_RWSTREAM_NoError)
290 return ErrorCode;
291
292 Pipe_ClearOUT();
293
294 ErrorCode = Pipe_WaitUntilReady();
295
296 Pipe_Freeze();
297
298 return ErrorCode;
299 }
300
301 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
302 {
303 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
304 return 0;
305
306 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
307 Pipe_Unfreeze();
308
309 if (Pipe_IsINReceived())
310 {
311 if (!(Pipe_BytesInPipe()))
312 {
313 Pipe_ClearIN();
314 Pipe_Freeze();
315 return 0;
316 }
317 else
318 {
319 Pipe_Freeze();
320 return Pipe_BytesInPipe();
321 }
322 }
323 else
324 {
325 Pipe_Freeze();
326
327 return 0;
328 }
329 }
330
331 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
332 {
333 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
334 return PIPE_RWSTREAM_DeviceDisconnected;
335
336 int16_t ReceivedByte = -1;
337
338 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipe.Address);
339 Pipe_Unfreeze();
340
341 if (Pipe_IsINReceived())
342 {
343 if (Pipe_BytesInPipe())
344 ReceivedByte = Pipe_Read_8();
345
346 if (!(Pipe_BytesInPipe()))
347 Pipe_ClearIN();
348 }
349
350 Pipe_Freeze();
351
352 return ReceivedByte;
353 }
354
355 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
356 char* const DeviceIDString,
357 const uint16_t BufferSize)
358 {
359 uint8_t ErrorCode;
360 uint16_t DeviceIDStringLength = 0;
361
362 USB_ControlRequest = (USB_Request_Header_t)
363 {
364 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
365 .bRequest = PRNT_REQ_GetDeviceID,
366 .wValue = 0,
367 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
368 .wLength = sizeof(DeviceIDStringLength),
369 };
370
371 Pipe_SelectPipe(PIPE_CONTROLPIPE);
372
373 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
374 return ErrorCode;
375
376 if (!(DeviceIDStringLength))
377 {
378 DeviceIDString[0] = 0x00;
379 return HOST_SENDCONTROL_Successful;
380 }
381
382 DeviceIDStringLength = be16_to_cpu(DeviceIDStringLength);
383
384 if (DeviceIDStringLength > BufferSize)
385 DeviceIDStringLength = BufferSize;
386
387 USB_ControlRequest.wLength = DeviceIDStringLength;
388
389 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
390 return ErrorCode;
391
392 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
393
394 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
395
396 return HOST_SENDCONTROL_Successful;
397 }
398
399 #endif
400
Imprint / Impressum