]> git.friedersdorff.com Git - max/tmk_keyboard.git/blob - tmk_core/protocol/lufa/LUFA-git/LUFA/Drivers/USB/Class/Host/PrinterClassHost.c
Merge commit '657d9f23fe47fb88cf221adb23095082f191ba6a'
[max/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