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