More simplifications to USBController.c, fix errors and warnings when compiled for...
[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_CLASS_HOST_C
36 #define __INCLUDE_FROM_PRINTER_DRIVER
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 uint8_t FoundEndpoints = 0;
44
45 memset(&PRNTInterfaceInfo->State, 0x00, sizeof(PRNTInterfaceInfo->State));
46
47 if (DESCRIPTOR_TYPE(DeviceConfigDescriptor) != DTYPE_Configuration)
48 return PRNT_ENUMERROR_InvalidConfigDescriptor;
49
50 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
51 DCOMP_PRNT_NextPRNTInterface) != DESCRIPTOR_SEARCH_COMP_Found)
52 {
53 return PRNT_ENUMERROR_NoPrinterInterfaceFound;
54 }
55
56 USB_Descriptor_Interface_t* PrinterInterface = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Interface_t);
57
58 PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
59 PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
60
61 while (FoundEndpoints != (PRNT_FOUND_DATAPIPE_IN | PRNT_FOUND_DATAPIPE_OUT))
62 {
63 if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &DeviceConfigDescriptor,
64 DCOMP_PRNT_NextPRNTInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
65 {
66 return PRNT_ENUMERROR_EndpointsNotFound;
67 }
68
69 USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(DeviceConfigDescriptor, USB_Descriptor_Endpoint_t);
70
71 if (EndpointData->EndpointAddress & ENDPOINT_DESCRIPTOR_DIR_IN)
72 {
73 Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataINPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_IN,
74 EndpointData->EndpointAddress, EndpointData->EndpointSize,
75 PRNTInterfaceInfo->Config.DataINPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
76 PRNTInterfaceInfo->State.DataINPipeSize = EndpointData->EndpointSize;
77
78 FoundEndpoints |= PRNT_FOUND_DATAPIPE_IN;
79 }
80 else
81 {
82 Pipe_ConfigurePipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber, EP_TYPE_BULK, PIPE_TOKEN_OUT,
83 EndpointData->EndpointAddress, EndpointData->EndpointSize,
84 PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE);
85 PRNTInterfaceInfo->State.DataOUTPipeSize = EndpointData->EndpointSize;
86
87 FoundEndpoints |= PRNT_FOUND_DATAPIPE_OUT;
88 }
89 }
90
91 PRNTInterfaceInfo->State.IsActive = true;
92 return PRNT_ENUMERROR_NoError;
93 }
94
95 static uint8_t DCOMP_PRNT_NextPRNTInterface(void* CurrentDescriptor)
96 {
97 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
98 {
99 if ((DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Class == PRINTER_CLASS) &&
100 (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).SubClass == PRINTER_SUBCLASS) &&
101 (DESCRIPTOR_CAST(CurrentDescriptor, USB_Descriptor_Interface_t).Protocol == PRINTER_PROTOCOL))
102 {
103 return DESCRIPTOR_SEARCH_Found;
104 }
105 }
106
107 return DESCRIPTOR_SEARCH_NotFound;
108 }
109
110 static uint8_t DCOMP_PRNT_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
111 {
112 if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Endpoint)
113 {
114 uint8_t EndpointType = (DESCRIPTOR_CAST(CurrentDescriptor,
115 USB_Descriptor_Endpoint_t).Attributes & EP_TYPE_MASK);
116
117 if (EndpointType == EP_TYPE_BULK)
118 return DESCRIPTOR_SEARCH_Found;
119 }
120 else if (DESCRIPTOR_TYPE(CurrentDescriptor) == DTYPE_Interface)
121 {
122 return DESCRIPTOR_SEARCH_Fail;
123 }
124
125 return DESCRIPTOR_SEARCH_NotFound;
126 }
127
128 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
129 {
130 PRNT_Host_Flush(PRNTInterfaceInfo);
131 }
132
133 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
134 {
135 if (PRNTInterfaceInfo->State.AlternateSetting)
136 {
137 uint8_t ErrorCode;
138
139 USB_ControlRequest = (USB_Request_Header_t)
140 {
141 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
142 .bRequest = REQ_SetInterface,
143 .wValue = PRNTInterfaceInfo->State.AlternateSetting,
144 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
145 .wLength = 0,
146 };
147
148 Pipe_SelectPipe(PIPE_CONTROLPIPE);
149
150 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
151 return ErrorCode;
152 }
153
154 return HOST_SENDCONTROL_Successful;
155 }
156
157 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
158 uint8_t* const PortStatus)
159 {
160 USB_ControlRequest = (USB_Request_Header_t)
161 {
162 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
163 .bRequest = REQ_GetPortStatus,
164 .wValue = 0,
165 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
166 .wLength = sizeof(uint8_t),
167 };
168
169 Pipe_SelectPipe(PIPE_CONTROLPIPE);
170
171 return USB_Host_SendControlRequest(PortStatus);
172 }
173
174 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
175 {
176 USB_ControlRequest = (USB_Request_Header_t)
177 {
178 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
179 .bRequest = REQ_SoftReset,
180 .wValue = 0,
181 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
182 .wLength = 0,
183 };
184
185 Pipe_SelectPipe(PIPE_CONTROLPIPE);
186
187 return USB_Host_SendControlRequest(NULL);
188 }
189
190 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
191 {
192 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
193 return PIPE_READYWAIT_DeviceDisconnected;
194
195 uint8_t ErrorCode;
196
197 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
198 Pipe_Unfreeze();
199
200 if (!(Pipe_BytesInPipe()))
201 return PIPE_READYWAIT_NoError;
202
203 bool BankFull = !(Pipe_IsReadWriteAllowed());
204
205 Pipe_ClearOUT();
206
207 if (BankFull)
208 {
209 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
210 return ErrorCode;
211
212 Pipe_ClearOUT();
213 }
214
215 Pipe_Freeze();
216
217 return PIPE_READYWAIT_NoError;
218 }
219
220 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
221 const uint8_t Data)
222 {
223 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
224 return PIPE_READYWAIT_DeviceDisconnected;
225
226 uint8_t ErrorCode;
227
228 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
229 Pipe_Unfreeze();
230
231 if (!(Pipe_IsReadWriteAllowed()))
232 {
233 Pipe_ClearOUT();
234
235 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
236 return ErrorCode;
237 }
238
239 Pipe_Write_Byte(Data);
240 Pipe_Freeze();
241
242 return PIPE_READYWAIT_NoError;
243 }
244
245 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
246 void* Buffer,
247 const uint16_t Length)
248 {
249 uint8_t ErrorCode;
250
251 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
252 return PIPE_RWSTREAM_DeviceDisconnected;
253
254 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
255 Pipe_Unfreeze();
256
257 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NO_STREAM_CALLBACK)) != PIPE_RWSTREAM_NoError)
258 return ErrorCode;
259
260 Pipe_ClearOUT();
261
262 ErrorCode = Pipe_WaitUntilReady();
263
264 Pipe_Freeze();
265
266 return ErrorCode;
267 }
268
269 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
270 {
271 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
272 return 0;
273
274 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
275 Pipe_Unfreeze();
276
277 if (Pipe_IsINReceived())
278 {
279 if (!(Pipe_BytesInPipe()))
280 {
281 Pipe_ClearIN();
282 Pipe_Freeze();
283 return 0;
284 }
285 else
286 {
287 Pipe_Freeze();
288 return Pipe_BytesInPipe();
289 }
290 }
291 else
292 {
293 Pipe_Freeze();
294
295 return 0;
296 }
297 }
298
299 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
300 {
301 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
302 return PIPE_RWSTREAM_DeviceDisconnected;
303
304 int16_t ReceivedByte = -1;
305
306 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
307 Pipe_Unfreeze();
308
309 if (Pipe_IsINReceived())
310 {
311 if (Pipe_BytesInPipe())
312 ReceivedByte = Pipe_Read_Byte();
313
314 if (!(Pipe_BytesInPipe()))
315 Pipe_ClearIN();
316 }
317
318 Pipe_Freeze();
319
320 return ReceivedByte;
321 }
322
323 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
324 char* const DeviceIDString,
325 const uint16_t BufferSize)
326 {
327 uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
328 uint16_t DeviceIDStringLength = 0;
329
330 USB_ControlRequest = (USB_Request_Header_t)
331 {
332 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
333 .bRequest = REQ_GetDeviceID,
334 .wValue = 0,
335 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
336 .wLength = sizeof(DeviceIDStringLength),
337 };
338
339 Pipe_SelectPipe(PIPE_CONTROLPIPE);
340
341 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
342 return ErrorCode;
343
344 if (!(DeviceIDStringLength))
345 {
346 DeviceIDString[0] = 0x00;
347 return HOST_SENDCONTROL_Successful;
348 }
349
350 DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
351
352 if (DeviceIDStringLength > BufferSize)
353 DeviceIDStringLength = BufferSize;
354
355 USB_ControlRequest.wLength = DeviceIDStringLength;
356
357 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
358 return ErrorCode;
359
360 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
361
362 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
363
364 return HOST_SENDCONTROL_Successful;
365 }
366
367 #endif