Statistics
| Branch: | Tag: | Revision:

root / LUFA / Drivers / USB / Class / Host / Printer.c @ 978b99e5

History | View | Annotate | Download (12.1 KB)

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_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 = HOST_SENDCONTROL_Successful;
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