Add structure padding to the appropriate descriptor structures to maintain correct...
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / Printer.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2011.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2011 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 "../../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 "Printer.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_DESCRIPTOR_DIR_IN)
76 DataINEndpoint = EndpointData;
77 else
78 DataOUTEndpoint = EndpointData;
79 }
80
81 for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
82 {
83 uint16_t Size;
84 uint8_t Type;
85 uint8_t Token;
86 uint8_t EndpointAddress;
87 bool DoubleBanked;
88
89 if (PipeNum == PRNTInterfaceInfo->Config.DataINPipeNumber)
90 {
91 Size = DataINEndpoint->EndpointSize;
92 EndpointAddress = DataINEndpoint->EndpointAddress;
93 Token = PIPE_TOKEN_IN;
94 Type = EP_TYPE_BULK;
95 DoubleBanked = PRNTInterfaceInfo->Config.DataINPipeDoubleBank;
96
97 PRNTInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
98 }
99 else if (PipeNum == PRNTInterfaceInfo->Config.DataOUTPipeNumber)
100 {
101 Size = DataOUTEndpoint->EndpointSize;
102 EndpointAddress = DataOUTEndpoint->EndpointAddress;
103 Token = PIPE_TOKEN_OUT;
104 Type = EP_TYPE_BULK;
105 DoubleBanked = PRNTInterfaceInfo->Config.DataOUTPipeDoubleBank;
106
107 PRNTInterfaceInfo->State.DataOUTPipeSize = DataOUTEndpoint->EndpointSize;
108 }
109 else
110 {
111 continue;
112 }
113
114 if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
115 DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
116 {
117 return PRNT_ENUMERROR_PipeConfigurationFailed;
118 }
119 }
120
121 PRNTInterfaceInfo->State.InterfaceNumber = PrinterInterface->InterfaceNumber;
122 PRNTInterfaceInfo->State.AlternateSetting = PrinterInterface->AlternateSetting;
123 PRNTInterfaceInfo->State.IsActive = true;
124
125 return PRNT_ENUMERROR_NoError;
126 }
127
128 static uint8_t DCOMP_PRNT_Host_NextPRNTInterface(void* CurrentDescriptor)
129 {
130 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
131
132 if (Header->Type == DTYPE_Interface)
133 {
134 USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
135
136 if ((Interface->Class == PRNT_CSCP_PrinterClass) &&
137 (Interface->SubClass == PRNT_CSCP_PrinterSubclass) &&
138 (Interface->Protocol == PRNT_CSCP_BidirectionalProtocol))
139 {
140 return DESCRIPTOR_SEARCH_Found;
141 }
142 }
143
144 return DESCRIPTOR_SEARCH_NotFound;
145 }
146
147 static uint8_t DCOMP_PRNT_Host_NextPRNTInterfaceEndpoint(void* CurrentDescriptor)
148 {
149 USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
150
151 if (Header->Type == DTYPE_Endpoint)
152 {
153 USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
154
155 uint8_t EndpointType = (Endpoint->Attributes & EP_TYPE_MASK);
156
157 if (EndpointType == EP_TYPE_BULK)
158 return DESCRIPTOR_SEARCH_Found;
159 }
160 else if (Header->Type == DTYPE_Interface)
161 {
162 return DESCRIPTOR_SEARCH_Fail;
163 }
164
165 return DESCRIPTOR_SEARCH_NotFound;
166 }
167
168 void PRNT_Host_USBTask(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
169 {
170 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
171 return;
172
173 #if !defined(NO_CLASS_DRIVER_AUTOFLUSH)
174 PRNT_Host_Flush(PRNTInterfaceInfo);
175 #endif
176 }
177
178 uint8_t PRNT_Host_SetBidirectionalMode(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
179 {
180 if (PRNTInterfaceInfo->State.AlternateSetting)
181 {
182 uint8_t ErrorCode;
183
184 USB_ControlRequest = (USB_Request_Header_t)
185 {
186 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_STANDARD | REQREC_INTERFACE),
187 .bRequest = REQ_SetInterface,
188 .wValue = PRNTInterfaceInfo->State.AlternateSetting,
189 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
190 .wLength = 0,
191 };
192
193 Pipe_SelectPipe(PIPE_CONTROLPIPE);
194
195 if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
196 return ErrorCode;
197 }
198
199 return HOST_SENDCONTROL_Successful;
200 }
201
202 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
203 uint8_t* const PortStatus)
204 {
205 USB_ControlRequest = (USB_Request_Header_t)
206 {
207 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
208 .bRequest = PRNT_REQ_GetPortStatus,
209 .wValue = 0,
210 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
211 .wLength = sizeof(uint8_t),
212 };
213
214 Pipe_SelectPipe(PIPE_CONTROLPIPE);
215
216 return USB_Host_SendControlRequest(PortStatus);
217 }
218
219 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
220 {
221 USB_ControlRequest = (USB_Request_Header_t)
222 {
223 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
224 .bRequest = PRNT_REQ_SoftReset,
225 .wValue = 0,
226 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
227 .wLength = 0,
228 };
229
230 Pipe_SelectPipe(PIPE_CONTROLPIPE);
231
232 return USB_Host_SendControlRequest(NULL);
233 }
234
235 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
236 {
237 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
238 return PIPE_READYWAIT_DeviceDisconnected;
239
240 uint8_t ErrorCode;
241
242 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
243 Pipe_Unfreeze();
244
245 if (!(Pipe_BytesInPipe()))
246 return PIPE_READYWAIT_NoError;
247
248 bool BankFull = !(Pipe_IsReadWriteAllowed());
249
250 Pipe_ClearOUT();
251
252 if (BankFull)
253 {
254 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
255 return ErrorCode;
256
257 Pipe_ClearOUT();
258 }
259
260 Pipe_Freeze();
261
262 return PIPE_READYWAIT_NoError;
263 }
264
265 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
266 const uint8_t Data)
267 {
268 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
269 return PIPE_READYWAIT_DeviceDisconnected;
270
271 uint8_t ErrorCode;
272
273 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
274 Pipe_Unfreeze();
275
276 if (!(Pipe_IsReadWriteAllowed()))
277 {
278 Pipe_ClearOUT();
279
280 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
281 return ErrorCode;
282 }
283
284 Pipe_Write_Byte(Data);
285 Pipe_Freeze();
286
287 return PIPE_READYWAIT_NoError;
288 }
289
290 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
291 void* String)
292 {
293 uint8_t ErrorCode;
294
295 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
296 return PIPE_RWSTREAM_DeviceDisconnected;
297
298 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
299 Pipe_Unfreeze();
300
301 if ((ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL)) != PIPE_RWSTREAM_NoError)
302 return ErrorCode;
303
304 Pipe_ClearOUT();
305
306 ErrorCode = Pipe_WaitUntilReady();
307
308 Pipe_Freeze();
309
310 return ErrorCode;
311 }
312
313 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
314 void* Buffer,
315 const uint16_t Length)
316 {
317 uint8_t ErrorCode;
318
319 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
320 return PIPE_RWSTREAM_DeviceDisconnected;
321
322 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
323 Pipe_Unfreeze();
324
325 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL)) != PIPE_RWSTREAM_NoError)
326 return ErrorCode;
327
328 Pipe_ClearOUT();
329
330 ErrorCode = Pipe_WaitUntilReady();
331
332 Pipe_Freeze();
333
334 return ErrorCode;
335 }
336
337 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
338 {
339 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
340 return 0;
341
342 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
343 Pipe_Unfreeze();
344
345 if (Pipe_IsINReceived())
346 {
347 if (!(Pipe_BytesInPipe()))
348 {
349 Pipe_ClearIN();
350 Pipe_Freeze();
351 return 0;
352 }
353 else
354 {
355 Pipe_Freeze();
356 return Pipe_BytesInPipe();
357 }
358 }
359 else
360 {
361 Pipe_Freeze();
362
363 return 0;
364 }
365 }
366
367 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
368 {
369 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
370 return PIPE_RWSTREAM_DeviceDisconnected;
371
372 int16_t ReceivedByte = -1;
373
374 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
375 Pipe_Unfreeze();
376
377 if (Pipe_IsINReceived())
378 {
379 if (Pipe_BytesInPipe())
380 ReceivedByte = Pipe_Read_Byte();
381
382 if (!(Pipe_BytesInPipe()))
383 Pipe_ClearIN();
384 }
385
386 Pipe_Freeze();
387
388 return ReceivedByte;
389 }
390
391 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
392 char* const DeviceIDString,
393 const uint16_t BufferSize)
394 {
395 uint8_t ErrorCode = HOST_SENDCONTROL_Successful;
396 uint16_t DeviceIDStringLength = 0;
397
398 USB_ControlRequest = (USB_Request_Header_t)
399 {
400 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
401 .bRequest = PRNT_REQ_GetDeviceID,
402 .wValue = 0,
403 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
404 .wLength = sizeof(DeviceIDStringLength),
405 };
406
407 Pipe_SelectPipe(PIPE_CONTROLPIPE);
408
409 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
410 return ErrorCode;
411
412 if (!(DeviceIDStringLength))
413 {
414 DeviceIDString[0] = 0x00;
415 return HOST_SENDCONTROL_Successful;
416 }
417
418 DeviceIDStringLength = SwapEndian_16(DeviceIDStringLength);
419
420 if (DeviceIDStringLength > BufferSize)
421 DeviceIDStringLength = BufferSize;
422
423 USB_ControlRequest.wLength = DeviceIDStringLength;
424
425 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
426 return ErrorCode;
427
428 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
429
430 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
431
432 return HOST_SENDCONTROL_Successful;
433 }
434
435 #endif
436