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