Documentation: Update copyrights to 2020.
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Device / PrinterClassDevice.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2020.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2020 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_DEVICE)
35
36 #define __INCLUDE_FROM_PRINTER_DRIVER
37 #define __INCLUDE_FROM_PRINTER_DEVICE_C
38 #include "PrinterClassDevice.h"
39
40 void PRNT_Device_ProcessControlRequest(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
41 {
42 if (!(Endpoint_IsSETUPReceived()))
43 return;
44
45 if (USB_ControlRequest.wIndex != PRNTInterfaceInfo->Config.InterfaceNumber)
46 return;
47
48 switch (USB_ControlRequest.bRequest)
49 {
50 case PRNT_REQ_GetDeviceID:
51 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
52 {
53 Endpoint_ClearSETUP();
54
55 while (!(Endpoint_IsINReady()))
56 {
57 if (USB_DeviceState == DEVICE_STATE_Unattached)
58 return;
59 }
60
61 uint16_t IEEEStringLen = strlen(PRNTInterfaceInfo->Config.IEEE1284String);
62 Endpoint_Write_16_BE(IEEEStringLen + sizeof(uint16_t));
63 Endpoint_Write_Control_Stream_LE(PRNTInterfaceInfo->Config.IEEE1284String, IEEEStringLen);
64 Endpoint_ClearStatusStage();
65 }
66
67 break;
68 case PRNT_REQ_GetPortStatus:
69 if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
70 {
71 Endpoint_ClearSETUP();
72
73 while (!(Endpoint_IsINReady()))
74 {
75 if (USB_DeviceState == DEVICE_STATE_Unattached)
76 return;
77 }
78
79 Endpoint_Write_8(PRNTInterfaceInfo->State.PortStatus);
80 Endpoint_ClearIN();
81
82 Endpoint_ClearStatusStage();
83 }
84
85 break;
86 case PRNT_REQ_SoftReset:
87 if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
88 {
89 Endpoint_ClearSETUP();
90 Endpoint_ClearStatusStage();
91
92 PRNTInterfaceInfo->State.IsPrinterReset = true;
93
94 EVENT_PRNT_Device_SoftReset(PRNTInterfaceInfo);
95 }
96
97 break;
98 }
99 }
100
101 bool PRNT_Device_ConfigureEndpoints(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
102 {
103 memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
104 PRNTInterfaceInfo->State.PortStatus = PRNT_PORTSTATUS_NOTERROR | PRNT_PORTSTATUS_SELECT;
105
106 PRNTInterfaceInfo->Config.DataINEndpoint.Type = EP_TYPE_BULK;
107 PRNTInterfaceInfo->Config.DataOUTEndpoint.Type = EP_TYPE_BULK;
108
109 if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataINEndpoint, 1)))
110 return false;
111
112 if (!(Endpoint_ConfigureEndpointTable(&PRNTInterfaceInfo->Config.DataOUTEndpoint, 1)))
113 return false;
114
115 return true;
116 }
117
118 void PRNT_Device_USBTask(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
119 {
120 if (USB_DeviceState != DEVICE_STATE_Configured)
121 return;
122
123 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
124 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
125
126 if (Endpoint_IsINReady())
127 PRNT_Device_Flush(PRNTInterfaceInfo);
128 #endif
129
130 if (PRNTInterfaceInfo->State.IsPrinterReset)
131 {
132 Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
133 Endpoint_ResetEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
134
135 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
136 Endpoint_ClearStall();
137 Endpoint_ResetDataToggle();
138 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
139 Endpoint_ClearStall();
140 Endpoint_ResetDataToggle();
141
142 PRNTInterfaceInfo->State.IsPrinterReset = false;
143 }
144 }
145
146 uint8_t PRNT_Device_SendString(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
147 const char* const String)
148 {
149 if (USB_DeviceState != DEVICE_STATE_Configured)
150 return ENDPOINT_RWSTREAM_DeviceDisconnected;
151
152 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
153 return Endpoint_Write_Stream_LE(String, strlen(String), NULL);
154 }
155
156 uint8_t PRNT_Device_SendData(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
157 const void* const Buffer,
158 const uint16_t Length)
159 {
160 if (USB_DeviceState != DEVICE_STATE_Configured)
161 return ENDPOINT_RWSTREAM_DeviceDisconnected;
162
163 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
164 return Endpoint_Write_Stream_LE(Buffer, Length, NULL);
165 }
166
167 uint8_t PRNT_Device_SendByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
168 const uint8_t Data)
169 {
170 if (USB_DeviceState != DEVICE_STATE_Configured)
171 return ENDPOINT_RWSTREAM_DeviceDisconnected;
172
173 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
174
175 if (!(Endpoint_IsReadWriteAllowed()))
176 {
177 Endpoint_ClearIN();
178
179 uint8_t ErrorCode;
180
181 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
182 return ErrorCode;
183 }
184
185 Endpoint_Write_8(Data);
186 return ENDPOINT_READYWAIT_NoError;
187 }
188
189 uint8_t PRNT_Device_Flush(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
190 {
191 if (USB_DeviceState != DEVICE_STATE_Configured)
192 return ENDPOINT_RWSTREAM_DeviceDisconnected;
193
194 uint8_t ErrorCode;
195
196 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataINEndpoint.Address);
197
198 if (!(Endpoint_BytesInEndpoint()))
199 return ENDPOINT_READYWAIT_NoError;
200
201 bool BankFull = !(Endpoint_IsReadWriteAllowed());
202
203 Endpoint_ClearIN();
204
205 if (BankFull)
206 {
207 if ((ErrorCode = Endpoint_WaitUntilReady()) != ENDPOINT_READYWAIT_NoError)
208 return ErrorCode;
209
210 Endpoint_ClearIN();
211 }
212
213 return ENDPOINT_READYWAIT_NoError;
214 }
215
216 uint16_t PRNT_Device_BytesReceived(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
217 {
218 if (USB_DeviceState != DEVICE_STATE_Configured)
219 return 0;
220
221 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
222
223 if (Endpoint_IsOUTReceived())
224 {
225 if (!(Endpoint_BytesInEndpoint()))
226 {
227 Endpoint_ClearOUT();
228 return 0;
229 }
230 else
231 {
232 return Endpoint_BytesInEndpoint();
233 }
234 }
235 else
236 {
237 return 0;
238 }
239 }
240
241 int16_t PRNT_Device_ReceiveByte(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
242 {
243 if (USB_DeviceState != DEVICE_STATE_Configured)
244 return -1;
245
246 int16_t ReceivedByte = -1;
247
248 Endpoint_SelectEndpoint(PRNTInterfaceInfo->Config.DataOUTEndpoint.Address);
249
250 if (Endpoint_IsOUTReceived())
251 {
252 if (Endpoint_BytesInEndpoint())
253 ReceivedByte = Endpoint_Read_8();
254
255 if (!(Endpoint_BytesInEndpoint()))
256 Endpoint_ClearOUT();
257 }
258
259 return ReceivedByte;
260 }
261
262 #if defined(FDEV_SETUP_STREAM)
263 void PRNT_Device_CreateStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
264 FILE* const Stream)
265 {
266 *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar, _FDEV_SETUP_RW);
267 fdev_set_udata(Stream, PRNTInterfaceInfo);
268 }
269
270 void PRNT_Device_CreateBlockingStream(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo,
271 FILE* const Stream)
272 {
273 *Stream = (FILE)FDEV_SETUP_STREAM(PRNT_Device_putchar, PRNT_Device_getchar_Blocking, _FDEV_SETUP_RW);
274 fdev_set_udata(Stream, PRNTInterfaceInfo);
275 }
276
277 static int PRNT_Device_putchar(char c,
278 FILE* Stream)
279 {
280 return PRNT_Device_SendByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream), c) ? _FDEV_ERR : 0;
281 }
282
283 static int PRNT_Device_getchar(FILE* Stream)
284 {
285 int16_t ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
286
287 if (ReceivedByte < 0)
288 return _FDEV_EOF;
289
290 return ReceivedByte;
291 }
292
293 static int PRNT_Device_getchar_Blocking(FILE* Stream)
294 {
295 int16_t ReceivedByte;
296
297 while ((ReceivedByte = PRNT_Device_ReceiveByte((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream))) < 0)
298 {
299 if (USB_DeviceState == DEVICE_STATE_Unattached)
300 return _FDEV_EOF;
301
302 PRNT_Device_USBTask((USB_ClassInfo_PRNT_Device_t*)fdev_get_udata(Stream));
303 USB_USBTask();
304 }
305
306 return ReceivedByte;
307 }
308 #endif
309
310 void PRNT_Device_Event_Stub(USB_ClassInfo_PRNT_Device_t* const PRNTInterfaceInfo)
311 {
312
313 }
314
315 #endif
316