Fix XPLAINBridge code broken during the changes to the Rescue Clock generation in...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / Printer.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2010.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2010 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 disclaim 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 "../../HighLevel/USBMode.h"
33 #if defined(USB_CAN_BE_HOST)
34
35 #define __INCLUDE_FROM_PRINTER_DRIVER
36 #define __INCLUDE_FROM_PRINTER_HOST_C
37 #include "Printer.h"
38
39 uint8_t PRNT_Host_ConfigurePipes(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
40 uint16_t ConfigDescriptorSize,
41 void* ConfigDescriptorData)
42 {
43 USB_Descriptor_Endpoint_t* DataINEndpoint = NULL;
44 USB_Descriptor_Endpoint_t* DataOUTEndpoint = NULL;
45 USB_Descriptor_Interface_t* PrinterInterface = NULL;
46
47 memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
48
49 if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
50 return PRNT_ENUMERROR_InvalidConfigDescriptor;
51
52 while (!(DataINEndpoint) || !(DataOUTEndpoint))
53 {
54 if (!(PrinterInterface) ||
55 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
56 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
57 {
58 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
59 DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
60 {
61 return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
62 }
63
64 PrinterInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
65
66 DataINEndpoint = NULL;
67 DataOUTEndpoint = NULL;
68
69 continue;
70 }
71
72 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
73
74 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
75 DataINEndpoint = EndpointData;
76 else
77 DataOUTEndpoint = EndpointData;
78 }
79
80 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
81 {
82 if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber)
83 {
84 Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_IN,
85 DataINEndpoint->EndpointAddress, DataINEndpoint->EndpointSize,
86 PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
87
88 PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
89 }
90 else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber)
91 {
92 Pipe_ConfigurePipe(PipeNum, EP_TYPE_BULK, PIPE_TOKEN_OUT,
93 DataOUTEndpoint->EndpointAddress, DataOUTEndpoint->EndpointSize,
94 PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
95
96 PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
97 }
98 }
99
100 PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
101 PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
102 PRNTInterfaceInfo->State.IsActive = true;
103
104 return PRNT_ENUMERROR_NoError;
105 }
106
107 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor)
108 {
109 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
110
111 if (Header->Type == DTYPE_Interface)
112 {
113 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
114
115 if ((Interface->Class == PRNT_CSCP_PrinterClass) &&
116 (Interface->SubClass == PRNT_CSCP_PrinterSubclass) &&
117 (Interface->Protocol == PRNT_CSCP_BidirectionalProtocol))
118 {
119 return DESCRIPTOR_SEARCH_Found;
120 }
121 }
122
123 return DESCRIPTOR_SEARCH_NotFound;
124 }
125
126 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
127 {
128 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
129
130 if (Header->Type == DTYPE_Endpoint)
131 {
132 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
133
134 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
135
136 if (EndpointType == EP_TYPE_BULK)
137 return DESCRIPTOR_SEARCH_Found;
138 }
139 else if (Header->Type == DTYPE_Interface)
140 {
141 return DESCRIPTOR_SEARCH_Fail;
142 }
143
144 return DESCRIPTOR_SEARCH_NotFound;
145 }
146
147 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
148 {
149 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
150 return;
151
152 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
153 PRNT_Host_Flush(PRNTInterfaceInfo);
154 #endif
155 }
156
157 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
158 {
159 if (PRNTInterfaceInfo->State.AlternateSetting)
160 {
161 uint8_t ErrorCode;
162
163 USB_ControlRequest = (USB_Request_Header_t)
164 {
165 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
166 .bRequest = REQ_SetInterface,
167 .wValue = PRNTInterfaceInfo->State.AlternateSetting,
168 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
169 .wLength = 0,
170 };
171
172 Pipe_SelectPipe(PIPE_CONTROLPIPE);
173
174 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
175 return ErrorCode;
176 }
177
178 return HOST_SENDCONTROL_Successful;
179 }
180
181 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
182 uint8_t* const PortStatus)
183 {
184 USB_ControlRequest = (USB_Request_Header_t)
185 {
186 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
187 .bRequest = PRNT_REQ_GetPortStatus,
188 .wValue = 0,
189 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
190 .wLength = sizeof(uint8_t),
191 };
192
193 Pipe_SelectPipe(PIPE_CONTROLPIPE);
194
195 return USB_Host_SendControlRequest(PortStatus);
196 }
197
198 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
199 {
200 USB_ControlRequest = (USB_Request_Header_t)
201 {
202 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
203 .bRequest = PRNT_REQ_SoftReset,
204 .wValue = 0,
205 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
206 .wLength = 0,
207 };
208
209 Pipe_SelectPipe(PIPE_CONTROLPIPE);
210
211 return USB_Host_SendControlRequest(NULL);
212 }
213
214 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
215 {
216 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
217 return PIPE_READYWAIT_DeviceDisconnected;
218
219 uint8_t ErrorCode;
220
221 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
222 Pipe_Unfreeze();
223
224 if (!(Pipe_BytesInPipe()))
225 return PIPE_READYWAIT_NoError;
226
227 bool BankFull = !(Pipe_IsReadWriteAllowed());
228
229 Pipe_ClearOUT();
230
231 if (BankFull)
232 {
233 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
234 return ErrorCode;
235
236 Pipe_ClearOUT();
237 }
238
239 Pipe_Freeze();
240
241 return PIPE_READYWAIT_NoError;
242 }
243
244 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
245 const uint8_t Data)
246 {
247 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
248 return PIPE_READYWAIT_DeviceDisconnected;
249
250 uint8_t ErrorCode;
251
252 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
253 Pipe_Unfreeze();
254
255 if (!(Pipe_IsReadWriteAllowed()))
256 {
257 Pipe_ClearOUT();
258
259 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
260 return ErrorCode;
261 }
262
263 Pipe_Write_Byte(Data);
264 Pipe_Freeze();
265
266 return PIPE_READYWAIT_NoError;
267 }
268
269 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
270 void* Buffer,
271 const uint16_t Length)
272 {
273 uint8_t ErrorCode;
274
275 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
276 return PIPE_RWSTREAM_DeviceDisconnected;
277
278 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
279 Pipe_Unfreeze();
280
281 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
282 return ErrorCode;
283
284 Pipe_ClearOUT();
285
286 ErrorCode = Pipe_WaitUntilReady();
287
288 Pipe_Freeze();
289
290 return ErrorCode;
291 }
292
293 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
294 {
295 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
296 return 0;
297
298 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
299 Pipe_Unfreeze();
300
301 if (Pipe_IsINReceived())
302 {
303 if (!(Pipe_BytesInPipe()))
304 {
305 Pipe_ClearIN();
306 Pipe_Freeze();
307 return 0;
308 }
309 else
310 {
311 Pipe_Freeze();
312 return Pipe_BytesInPipe();
313 }
314 }
315 else
316 {
317 Pipe_Freeze();
318
319 return 0;
320 }
321 }
322
323 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
324 {
325 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
326 return PIPE_RWSTREAM_DeviceDisconnected;
327
328 int16_t ReceivedByte = -1;
329
330 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
331 Pipe_Unfreeze();
332
333 if (Pipe_IsINReceived())
334 {
335 if (Pipe_BytesInPipe())
336 ReceivedByte = Pipe_Read_Byte();
337
338 if (!(Pipe_BytesInPipe()))
339 Pipe_ClearIN();
340 }
341
342 Pipe_Freeze();
343
344 return ReceivedByte;
345 }
346
347 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
348 char* const DeviceIDString,
349 const uint16_t BufferSize)
350 {
351 uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
352 uint16_t DeviceIDStringLength = 0;
353
354 USB_ControlRequest = (USB_Request_Header_t)
355 {
356 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
357 .bRequest = PRNT_REQ_GetDeviceID,
358 .wValue = 0,
359 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
360 .wLength = sizeof(DeviceIDStringLength),
361 };
362
363 Pipe_SelectPipe(PIPE_CONTROLPIPE);
364
365 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
366 return ErrorCode;
367
368 if (!(DeviceIDStringLength))
369 {
370 DeviceIDString[0] = 0x00;
371 return HOST_SENDCONTROL_Successful;
372 }
373
374 DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
375
376 if (DeviceIDStringLength > BufferSize)
377 DeviceIDStringLength = BufferSize;
378
379 USB_ControlRequest.wLength = DeviceIDStringLength;
380
381 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
382 return ErrorCode;
383
384 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
385
386 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
387
388 return HOST_SENDCONTROL_Successful;
389 }
390
391 #endif
392