All USB class drivers are now automatically included when LUFA/Drivers/USB.h is inclu...
[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.fourwalledcubicle.com
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* DeviceConfigDescriptor)
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(DeviceConfigDescriptor) != DTYPE_Configuration)
50 return PRNT_ENUMERROR_InvalidConfigDescriptor;
51
52 while (!(DataINEndpoint) || !(DataOUTEndpoint))
53 {
54 if (!(PrinterInterface) ||
55 USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
56 DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
57 {
58 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
59 DCOMP_PRNT_Host_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
60 {
61 return PRNT_ENUMERROR_NoCompatibleInterfaceFound;
62 }
63
64 PrinterInterface = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t);
65
66 DataINEndpoint = NULL;
67 DataOUTEndpoint = NULL;
68
69 continue;
70 }
71
72 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, 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 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
110 {
111 USB_Descriptor_Interface_t* CurrentInterface = DESCRIPTOR_PCAST(CurrentDescriptor,
112 USB_Descriptor_Interface_t);
113
114 if ((CurrentInterface->Class == PRINTER_CLASS) &&
115 (CurrentInterface->SubClass == PRINTER_SUBCLASS) &&
116 (CurrentInterface->Protocol == PRINTER_PROTOCOL))
117 {
118 return DESCRIPTOR_SEARCH_Found;
119 }
120 }
121
122 return DESCRIPTOR_SEARCH_NotFound;
123 }
124
125 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
126 {
127 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
128 {
129 uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor,
130 USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK);
131
132 if (EndpointType == EP_TYPE_BULK)
133 return DESCRIPTOR_SEARCH_Found;
134 }
135 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
136 {
137 return DESCRIPTOR_SEARCH_Fail;
138 }
139
140 return DESCRIPTOR_SEARCH_NotFound;
141 }
142
143 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
144 {
145 PRNT_Host_Flush(PRNTInterfaceInfo);
146 }
147
148 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
149 {
150 if (PRNTInterfaceInfo->State.AlternateSetting)
151 {
152 uint8_t ErrorCode;
153
154 USB_ControlRequest = (USB_Request_Header_t)
155 {
156 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
157 .bRequest = REQ_SetInterface,
158 .wValue = PRNTInterfaceInfo->State.AlternateSetting,
159 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
160 .wLength = 0,
161 };
162
163 Pipe_SelectPipe(PIPE_CONTROLPIPE);
164
165 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
166 return ErrorCode;
167 }
168
169 return HOST_SENDCONTROL_Successful;
170 }
171
172 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
173 uint8_t* const PortStatus)
174 {
175 USB_ControlRequest = (USB_Request_Header_t)
176 {
177 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
178 .bRequest = PRNT_REQ_GetPortStatus,
179 .wValue = 0,
180 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
181 .wLength = sizeof(uint8_t),
182 };
183
184 Pipe_SelectPipe(PIPE_CONTROLPIPE);
185
186 return USB_Host_SendControlRequest(PortStatus);
187 }
188
189 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
190 {
191 USB_ControlRequest = (USB_Request_Header_t)
192 {
193 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
194 .bRequest = PRNT_REQ_SoftReset,
195 .wValue = 0,
196 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
197 .wLength = 0,
198 };
199
200 Pipe_SelectPipe(PIPE_CONTROLPIPE);
201
202 return USB_Host_SendControlRequest(NULL);
203 }
204
205 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
206 {
207 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
208 return PIPE_READYWAIT_DeviceDisconnected;
209
210 uint8_t ErrorCode;
211
212 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
213 Pipe_Unfreeze();
214
215 if (!(Pipe_BytesInPipe()))
216 return PIPE_READYWAIT_NoError;
217
218 bool BankFull = !(Pipe_IsReadWriteAllowed());
219
220 Pipe_ClearOUT();
221
222 if (BankFull)
223 {
224 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
225 return ErrorCode;
226
227 Pipe_ClearOUT();
228 }
229
230 Pipe_Freeze();
231
232 return PIPE_READYWAIT_NoError;
233 }
234
235 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
236 const uint8_t Data)
237 {
238 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
239 return PIPE_READYWAIT_DeviceDisconnected;
240
241 uint8_t ErrorCode;
242
243 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
244 Pipe_Unfreeze();
245
246 if (!(Pipe_IsReadWriteAllowed()))
247 {
248 Pipe_ClearOUT();
249
250 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
251 return ErrorCode;
252 }
253
254 Pipe_Write_Byte(Data);
255 Pipe_Freeze();
256
257 return PIPE_READYWAIT_NoError;
258 }
259
260 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
261 void* Buffer,
262 const uint16_t Length)
263 {
264 uint8_t ErrorCode;
265
266 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
267 return PIPE_RWSTREAM_DeviceDisconnected;
268
269 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
270 Pipe_Unfreeze();
271
272 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
273 return ErrorCode;
274
275 Pipe_ClearOUT();
276
277 ErrorCode = Pipe_WaitUntilReady();
278
279 Pipe_Freeze();
280
281 return ErrorCode;
282 }
283
284 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
285 {
286 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
287 return 0;
288
289 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
290 Pipe_Unfreeze();
291
292 if (Pipe_IsINReceived())
293 {
294 if (!(Pipe_BytesInPipe()))
295 {
296 Pipe_ClearIN();
297 Pipe_Freeze();
298 return 0;
299 }
300 else
301 {
302 Pipe_Freeze();
303 return Pipe_BytesInPipe();
304 }
305 }
306 else
307 {
308 Pipe_Freeze();
309
310 return 0;
311 }
312 }
313
314 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
315 {
316 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
317 return PIPE_RWSTREAM_DeviceDisconnected;
318
319 int16_t ReceivedByte = -1;
320
321 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
322 Pipe_Unfreeze();
323
324 if (Pipe_IsINReceived())
325 {
326 if (Pipe_BytesInPipe())
327 ReceivedByte = Pipe_Read_Byte();
328
329 if (!(Pipe_BytesInPipe()))
330 Pipe_ClearIN();
331 }
332
333 Pipe_Freeze();
334
335 return ReceivedByte;
336 }
337
338 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
339 char* const DeviceIDString,
340 const uint16_t BufferSize)
341 {
342 uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
343 uint16_t DeviceIDStringLength = 0;
344
345 USB_ControlRequest = (USB_Request_Header_t)
346 {
347 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
348 .bRequest = PRNT_REQ_GetDeviceID,
349 .wValue = 0,
350 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
351 .wLength = sizeof(DeviceIDStringLength),
352 };
353
354 Pipe_SelectPipe(PIPE_CONTROLPIPE);
355
356 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
357 return ErrorCode;
358
359 if (!(DeviceIDStringLength))
360 {
361 DeviceIDString[0] = 0x00;
362 return HOST_SENDCONTROL_Successful;
363 }
364
365 DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
366
367 if (DeviceIDStringLength > BufferSize)
368 DeviceIDStringLength = BufferSize;
369
370 USB_ControlRequest.wLength = DeviceIDStringLength;
371
372 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
373 return ErrorCode;
374
375 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
376
377 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
378
379 return HOST_SENDCONTROL_Successful;
380 }
381
382 #endif
383