Add new tag for the LUFA-120219-BETA release.
[pub/USBasp.git] / LUFA / Drivers / USB / Class / Host / PrinterClassHost.c
1 /*
2 LUFA Library
3 Copyright (C) Dean Camera, 2012.
4
5 dean [at] fourwalledcubicle [dot] com
6 www.lufa-lib.org
7 */
8
9 /*
10 Copyright 2012 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 "PrinterClassHost.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_DIR_MASK) == ENDPOINT_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 = le16_to_cpu(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 = le16_to_cpu(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 if ((ErrorCode = USB_Host_SetInterfaceAltSetting(PRNTInterfaceInfo->State.InterfaceNumber,
185 PRNTInterfaceInfo->State.AlternateSetting)) != HOST_SENDCONTROL_Successful)
186 {
187 return ErrorCode;
188 }
189 }
190
191 return HOST_SENDCONTROL_Successful;
192 }
193
194 uint8_t PRNT_Host_GetPortStatus(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
195 uint8_t* const PortStatus)
196 {
197 USB_ControlRequest = (USB_Request_Header_t)
198 {
199 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
200 .bRequest = PRNT_REQ_GetPortStatus,
201 .wValue = 0,
202 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
203 .wLength = sizeof(uint8_t),
204 };
205
206 Pipe_SelectPipe(PIPE_CONTROLPIPE);
207 return USB_Host_SendControlRequest(PortStatus);
208 }
209
210 uint8_t PRNT_Host_SoftReset(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
211 {
212 USB_ControlRequest = (USB_Request_Header_t)
213 {
214 .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
215 .bRequest = PRNT_REQ_SoftReset,
216 .wValue = 0,
217 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
218 .wLength = 0,
219 };
220
221 Pipe_SelectPipe(PIPE_CONTROLPIPE);
222 return USB_Host_SendControlRequest(NULL);
223 }
224
225 uint8_t PRNT_Host_Flush(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
226 {
227 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
228 return PIPE_READYWAIT_DeviceDisconnected;
229
230 uint8_t ErrorCode;
231
232 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
233 Pipe_Unfreeze();
234
235 if (!(Pipe_BytesInPipe()))
236 return PIPE_READYWAIT_NoError;
237
238 bool BankFull = !(Pipe_IsReadWriteAllowed());
239
240 Pipe_ClearOUT();
241
242 if (BankFull)
243 {
244 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
245 return ErrorCode;
246
247 Pipe_ClearOUT();
248 }
249
250 Pipe_Freeze();
251
252 return PIPE_READYWAIT_NoError;
253 }
254
255 uint8_t PRNT_Host_SendByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
256 const uint8_t Data)
257 {
258 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
259 return PIPE_READYWAIT_DeviceDisconnected;
260
261 uint8_t ErrorCode;
262
263 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
264 Pipe_Unfreeze();
265
266 if (!(Pipe_IsReadWriteAllowed()))
267 {
268 Pipe_ClearOUT();
269
270 if ((ErrorCode = Pipe_WaitUntilReady()) != PIPE_READYWAIT_NoError)
271 return ErrorCode;
272 }
273
274 Pipe_Write_8(Data);
275 Pipe_Freeze();
276
277 return PIPE_READYWAIT_NoError;
278 }
279
280 uint8_t PRNT_Host_SendString(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
281 void* String)
282 {
283 uint8_t ErrorCode;
284
285 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
286 return PIPE_RWSTREAM_DeviceDisconnected;
287
288 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
289 Pipe_Unfreeze();
290
291 if ((ErrorCode = Pipe_Write_Stream_LE(String, strlen(String), NULL)) != PIPE_RWSTREAM_NoError)
292 return ErrorCode;
293
294 Pipe_ClearOUT();
295
296 ErrorCode = Pipe_WaitUntilReady();
297
298 Pipe_Freeze();
299
300 return ErrorCode;
301 }
302
303 uint8_t PRNT_Host_SendData(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
304 void* Buffer,
305 const uint16_t Length)
306 {
307 uint8_t ErrorCode;
308
309 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
310 return PIPE_RWSTREAM_DeviceDisconnected;
311
312 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataOUTPipeNumber);
313 Pipe_Unfreeze();
314
315 if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, Length, NULL)) != PIPE_RWSTREAM_NoError)
316 return ErrorCode;
317
318 Pipe_ClearOUT();
319
320 ErrorCode = Pipe_WaitUntilReady();
321
322 Pipe_Freeze();
323
324 return ErrorCode;
325 }
326
327 uint16_t PRNT_Host_BytesReceived(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
328 {
329 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
330 return 0;
331
332 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
333 Pipe_Unfreeze();
334
335 if (Pipe_IsINReceived())
336 {
337 if (!(Pipe_BytesInPipe()))
338 {
339 Pipe_ClearIN();
340 Pipe_Freeze();
341 return 0;
342 }
343 else
344 {
345 Pipe_Freeze();
346 return Pipe_BytesInPipe();
347 }
348 }
349 else
350 {
351 Pipe_Freeze();
352
353 return 0;
354 }
355 }
356
357 int16_t PRNT_Host_ReceiveByte(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo)
358 {
359 if ((USB_HostState != HOST_STATE_Configured) || !(PRNTInterfaceInfo->State.IsActive))
360 return PIPE_RWSTREAM_DeviceDisconnected;
361
362 int16_t ReceivedByte = -1;
363
364 Pipe_SelectPipe(PRNTInterfaceInfo->Config.DataINPipeNumber);
365 Pipe_Unfreeze();
366
367 if (Pipe_IsINReceived())
368 {
369 if (Pipe_BytesInPipe())
370 ReceivedByte = Pipe_Read_8();
371
372 if (!(Pipe_BytesInPipe()))
373 Pipe_ClearIN();
374 }
375
376 Pipe_Freeze();
377
378 return ReceivedByte;
379 }
380
381 uint8_t PRNT_Host_GetDeviceID(USB_ClassInfo_PRNT_Host_t* const PRNTInterfaceInfo,
382 char* const DeviceIDString,
383 const uint16_t BufferSize)
384 {
385 uint8_t ErrorCode;
386 uint16_t DeviceIDStringLength = 0;
387
388 USB_ControlRequest = (USB_Request_Header_t)
389 {
390 .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
391 .bRequest = PRNT_REQ_GetDeviceID,
392 .wValue = 0,
393 .wIndex = PRNTInterfaceInfo->State.InterfaceNumber,
394 .wLength = sizeof(DeviceIDStringLength),
395 };
396
397 Pipe_SelectPipe(PIPE_CONTROLPIPE);
398
399 if ((ErrorCode = USB_Host_SendControlRequest(&DeviceIDStringLength)) != HOST_SENDCONTROL_Successful)
400 return ErrorCode;
401
402 if (!(DeviceIDStringLength))
403 {
404 DeviceIDString[0] = 0x00;
405 return HOST_SENDCONTROL_Successful;
406 }
407
408 DeviceIDStringLength = be16_to_cpu(DeviceIDStringLength);
409
410 if (DeviceIDStringLength > BufferSize)
411 DeviceIDStringLength = BufferSize;
412
413 USB_ControlRequest.wLength = DeviceIDStringLength;
414
415 if ((ErrorCode = USB_Host_SendControlRequest(DeviceIDString)) != HOST_SENDCONTROL_Successful)
416 return ErrorCode;
417
418 memmove(&DeviceIDString[0], &DeviceIDString[2], DeviceIDStringLength - 2);
419
420 DeviceIDString[DeviceIDStringLength - 2] = 0x00;
421
422 return HOST_SENDCONTROL_Successful;
423 }
424
425 #endif
426