Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (13.6 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_HID_DRIVER
37
#define  __INCLUDE_FROM_HID_HOST_C
38
#include "HID.h"
39

    
40
uint8_t HID_Host_ConfigurePipes(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
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* HIDInterface    = NULL;
47
        USB_HID_Descriptor_HID_t*   HIDDescriptor   = NULL;
48

    
49
        memset(&HIDInterfaceInfo->State, 0x00, sizeof(HIDInterfaceInfo->State));
50

    
51
        if (DESCRIPTOR_TYPE(ConfigDescriptorData) != DTYPE_Configuration)
52
          return HID_ENUMERROR_InvalidConfigDescriptor;
53

    
54
        while (!(DataINEndpoint) || !(DataOUTEndpoint))
55
        {
56
                if (!(HIDInterface) ||
57
                    USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
58
                                              DCOMP_HID_Host_NextHIDInterfaceEndpoint) != DESCRIPTOR_SEARCH_COMP_Found)
59
                {
60
                        if (DataINEndpoint || DataOUTEndpoint)
61
                          break;
62

    
63
                        do
64
                        {
65
                                if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
66
                                                              DCOMP_HID_Host_NextHIDInterface) != DESCRIPTOR_SEARCH_COMP_Found)
67
                                {
68
                                        return HID_ENUMERROR_NoCompatibleInterfaceFound;
69
                                }
70

    
71
                                HIDInterface = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Interface_t);
72
                        } while (HIDInterfaceInfo->Config.HIDInterfaceProtocol &&
73
                                         (HIDInterface->Protocol != HIDInterfaceInfo->Config.HIDInterfaceProtocol));
74

    
75
                        if (USB_GetNextDescriptorComp(&ConfigDescriptorSize, &ConfigDescriptorData,
76
                                                      DCOMP_HID_Host_NextHIDDescriptor) != DESCRIPTOR_SEARCH_COMP_Found)
77
                        {
78
                                return HID_ENUMERROR_NoCompatibleInterfaceFound;
79
                        }
80

    
81
                        HIDDescriptor = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_HID_Descriptor_HID_t);
82

    
83
                        DataINEndpoint  = NULL;
84
                        DataOUTEndpoint = NULL;
85

    
86
                        continue;
87
                }
88

    
89
                USB_Descriptor_Endpoint_t* EndpointData = DESCRIPTOR_PCAST(ConfigDescriptorData, USB_Descriptor_Endpoint_t);
90

    
91
                if ((EndpointData->EndpointAddress & ENDPOINT_DIR_MASK) == ENDPOINT_DIR_IN)
92
                  DataINEndpoint  = EndpointData;
93
                else
94
                  DataOUTEndpoint = EndpointData;
95
        }
96

    
97
        for (uint8_t PipeNum = 1; PipeNum < PIPE_TOTAL_PIPES; PipeNum++)
98
        {
99
                uint16_t Size;
100
                uint8_t  Type;
101
                uint8_t  Token;
102
                uint8_t  EndpointAddress;
103
                uint8_t  InterruptPeriod;
104
                bool     DoubleBanked;
105

    
106
                if (PipeNum == HIDInterfaceInfo->Config.DataINPipeNumber)
107
                {
108
                        Size            = le16_to_cpu(DataINEndpoint->EndpointSize);
109
                        EndpointAddress = DataINEndpoint->EndpointAddress;
110
                        Token           = PIPE_TOKEN_IN;
111
                        Type            = EP_TYPE_INTERRUPT;
112
                        DoubleBanked    = HIDInterfaceInfo->Config.DataINPipeDoubleBank;
113
                        InterruptPeriod = DataINEndpoint->PollingIntervalMS;
114

    
115
                        HIDInterfaceInfo->State.DataINPipeSize = DataINEndpoint->EndpointSize;
116
                }
117
                else if (PipeNum == HIDInterfaceInfo->Config.DataOUTPipeNumber)
118
                {
119
                        if (DataOUTEndpoint == NULL)
120
                          continue;
121
                
122
                        Size            = le16_to_cpu(DataOUTEndpoint->EndpointSize);
123
                        EndpointAddress = DataOUTEndpoint->EndpointAddress;
124
                        Token           = PIPE_TOKEN_OUT;
125
                        Type            = EP_TYPE_INTERRUPT;
126
                        DoubleBanked    = HIDInterfaceInfo->Config.DataOUTPipeDoubleBank;
127
                        InterruptPeriod = DataOUTEndpoint->PollingIntervalMS;
128

    
129
                        HIDInterfaceInfo->State.DataOUTPipeSize   = DataOUTEndpoint->EndpointSize;
130
                        HIDInterfaceInfo->State.DeviceUsesOUTPipe = true;
131
                }
132
                else
133
                {
134
                        continue;
135
                }
136

    
137
                if (!(Pipe_ConfigurePipe(PipeNum, Type, Token, EndpointAddress, Size,
138
                                         DoubleBanked ? PIPE_BANK_DOUBLE : PIPE_BANK_SINGLE)))
139
                {
140
                        return HID_ENUMERROR_PipeConfigurationFailed;
141
                }
142
                
143
                if (InterruptPeriod)
144
                  Pipe_SetInterruptPeriod(InterruptPeriod);
145
        }
146

    
147
        HIDInterfaceInfo->State.InterfaceNumber      = HIDInterface->InterfaceNumber;
148
        HIDInterfaceInfo->State.HIDReportSize        = LE16_TO_CPU(HIDDescriptor->HIDReportLength);
149
        HIDInterfaceInfo->State.SupportsBootProtocol = (HIDInterface->SubClass != HID_CSCP_NonBootProtocol);
150
        HIDInterfaceInfo->State.LargestReportSize    = 8;
151
        HIDInterfaceInfo->State.IsActive             = true;
152

    
153
        return HID_ENUMERROR_NoError;
154
}
155

    
156
static uint8_t DCOMP_HID_Host_NextHIDInterface(void* const CurrentDescriptor)
157
{
158
        USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
159

    
160
        if (Header->Type == DTYPE_Interface)
161
        {
162
                USB_Descriptor_Interface_t* Interface = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Interface_t);
163

    
164
                if (Interface->Class == HID_CSCP_HIDClass)
165
                  return DESCRIPTOR_SEARCH_Found;
166
        }
167

    
168
        return DESCRIPTOR_SEARCH_NotFound;
169
}
170

    
171
static uint8_t DCOMP_HID_Host_NextHIDDescriptor(void* const CurrentDescriptor)
172
{
173
        USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
174

    
175
        if (Header->Type == HID_DTYPE_HID)
176
          return DESCRIPTOR_SEARCH_Found;
177
        else if (Header->Type == DTYPE_Interface)
178
          return DESCRIPTOR_SEARCH_Fail;
179
        else
180
          return DESCRIPTOR_SEARCH_NotFound;
181
}
182

    
183
static uint8_t DCOMP_HID_Host_NextHIDInterfaceEndpoint(void* const CurrentDescriptor)
184
{
185
        USB_Descriptor_Header_t* Header = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Header_t);
186

    
187
        if (Header->Type == DTYPE_Endpoint)
188
        {
189
                USB_Descriptor_Endpoint_t* Endpoint = DESCRIPTOR_PCAST(CurrentDescriptor, USB_Descriptor_Endpoint_t);
190

    
191
                if (!(Pipe_IsEndpointBound(Endpoint->EndpointAddress)))
192
                  return DESCRIPTOR_SEARCH_Found;
193
        }
194
        else if (Header->Type == DTYPE_Interface)
195
        {
196
                return DESCRIPTOR_SEARCH_Fail;
197
        }
198

    
199
        return DESCRIPTOR_SEARCH_NotFound;
200
}
201

    
202
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
203
uint8_t HID_Host_ReceiveReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
204
                                   const uint8_t ReportID,
205
                                   void* Buffer)
206
{
207
        USB_ControlRequest = (USB_Request_Header_t)
208
        {
209
                .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
210
                .bRequest      = HID_REQ_SetReport,
211
                .wValue        = ((HID_REPORT_ITEM_In + 1) << 8) | ReportID,
212
                .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
213
                .wLength       = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In),
214
        };
215

    
216
        Pipe_SelectPipe(PIPE_CONTROLPIPE);
217

    
218
        return USB_Host_SendControlRequest(Buffer);
219
}
220
#endif
221

    
222
uint8_t HID_Host_ReceiveReport(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
223
                               void* Buffer)
224
{
225
        if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
226
          return PIPE_READYWAIT_DeviceDisconnected;
227

    
228
        uint8_t ErrorCode;
229

    
230
        Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
231
        Pipe_Unfreeze();
232

    
233
        uint16_t ReportSize;
234
        uint8_t* BufferPos = Buffer;
235

    
236
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
237
        if (!(HIDInterfaceInfo->State.UsingBootProtocol))
238
        {
239
                uint8_t ReportID = 0;
240

    
241
                if (HIDInterfaceInfo->Config.HIDParserData->UsingReportIDs)
242
                {
243
                        ReportID = Pipe_Read_8();
244
                        *(BufferPos++) = ReportID;
245
                }
246

    
247
                ReportSize = USB_GetHIDReportSize(HIDInterfaceInfo->Config.HIDParserData, ReportID, HID_REPORT_ITEM_In);
248
        }
249
        else
250
#endif
251
        {
252
                ReportSize = Pipe_BytesInPipe();
253
        }
254

    
255
        if ((ErrorCode = Pipe_Read_Stream_LE(BufferPos, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
256
          return ErrorCode;
257

    
258
        Pipe_ClearIN();
259
        Pipe_Freeze();
260

    
261
        return PIPE_RWSTREAM_NoError;
262
}
263

    
264
uint8_t HID_Host_SendReportByID(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
265
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
266
                                const uint8_t ReportID,
267
#endif
268
                                const uint8_t ReportType,
269
                                void* Buffer,
270
                                const uint16_t ReportSize)
271
{
272
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
273
        if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
274
          return false;
275

    
276
        if (HIDInterfaceInfo->State.DeviceUsesOUTPipe && (ReportType == HID_REPORT_ITEM_Out))
277
        {
278
                uint8_t ErrorCode;
279

    
280
                Pipe_SelectPipe(HIDInterfaceInfo->Config.DataOUTPipeNumber);
281
                Pipe_Unfreeze();
282

    
283
                if (ReportID)
284
                  Pipe_Write_Stream_LE(&ReportID, sizeof(ReportID), NULL);
285

    
286
                if ((ErrorCode = Pipe_Write_Stream_LE(Buffer, ReportSize, NULL)) != PIPE_RWSTREAM_NoError)
287
                  return ErrorCode;
288

    
289
                Pipe_ClearOUT();
290
                Pipe_Freeze();
291

    
292
                return PIPE_RWSTREAM_NoError;
293
        }
294
        else
295
#endif
296
        {
297
                USB_ControlRequest = (USB_Request_Header_t)
298
                {
299
                        .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
300
                        .bRequest      = HID_REQ_SetReport,
301
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
302
                        .wValue        = ((ReportType + 1) << 8) | ReportID,
303
#else
304
                        .wValue        = ((ReportType + 1) << 8),
305
#endif
306
                        .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
307
                        .wLength       = ReportSize,
308
                };
309

    
310
                Pipe_SelectPipe(PIPE_CONTROLPIPE);
311

    
312
                return USB_Host_SendControlRequest(Buffer);
313
        }
314
}
315

    
316
bool HID_Host_IsReportReceived(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
317
{
318
        if ((USB_HostState != HOST_STATE_Configured) || !(HIDInterfaceInfo->State.IsActive))
319
          return false;
320

    
321
        bool ReportReceived;
322

    
323
        Pipe_SelectPipe(HIDInterfaceInfo->Config.DataINPipeNumber);
324
        Pipe_Unfreeze();
325

    
326
        ReportReceived = Pipe_IsINReceived();
327

    
328
        Pipe_Freeze();
329

    
330
        return ReportReceived;
331
}
332

    
333
uint8_t HID_Host_SetBootProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
334
{
335
        uint8_t ErrorCode;
336

    
337
        if (!(HIDInterfaceInfo->State.SupportsBootProtocol))
338
          return HID_ERROR_LOGICAL;
339

    
340
        USB_ControlRequest = (USB_Request_Header_t)
341
                {
342
                        .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
343
                        .bRequest      = HID_REQ_SetProtocol,
344
                        .wValue        = 0,
345
                        .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
346
                        .wLength       = 0,
347
                };
348

    
349
        Pipe_SelectPipe(PIPE_CONTROLPIPE);
350

    
351
        if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
352
          return ErrorCode;
353

    
354
        HIDInterfaceInfo->State.LargestReportSize = 8;
355
        HIDInterfaceInfo->State.UsingBootProtocol = true;
356

    
357
        return HOST_SENDCONTROL_Successful;
358
}
359

    
360
uint8_t HID_Host_SetIdlePeriod(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo,
361
                               const uint16_t MS)
362
{
363
        USB_ControlRequest = (USB_Request_Header_t)
364
                {
365
                        .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
366
                        .bRequest      = HID_REQ_SetIdle,
367
                        .wValue        = ((MS << 6) & 0xFF00),
368
                        .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
369
                        .wLength       = 0,
370
                };
371

    
372
        Pipe_SelectPipe(PIPE_CONTROLPIPE);
373

    
374
        return USB_Host_SendControlRequest(NULL);
375
}
376

    
377
#if !defined(HID_HOST_BOOT_PROTOCOL_ONLY)
378
uint8_t HID_Host_SetReportProtocol(USB_ClassInfo_HID_Host_t* const HIDInterfaceInfo)
379
{
380
        uint8_t ErrorCode;
381

    
382
        uint8_t HIDReportData[HIDInterfaceInfo->State.HIDReportSize];
383

    
384
        USB_ControlRequest = (USB_Request_Header_t)
385
                {
386
                        .bmRequestType = (REQDIR_DEVICETOHOST | REQTYPE_STANDARD | REQREC_INTERFACE),
387
                        .bRequest      = REQ_GetDescriptor,
388
                        .wValue        = (HID_DTYPE_Report << 8),
389
                        .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
390
                        .wLength       = HIDInterfaceInfo->State.HIDReportSize,
391
                };
392

    
393
        Pipe_SelectPipe(PIPE_CONTROLPIPE);
394

    
395
        if ((ErrorCode = USB_Host_SendControlRequest(HIDReportData)) != HOST_SENDCONTROL_Successful)
396
          return ErrorCode;
397

    
398
        if (HIDInterfaceInfo->State.UsingBootProtocol)
399
        {
400
                USB_ControlRequest = (USB_Request_Header_t)
401
                        {
402
                                .bmRequestType = (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE),
403
                                .bRequest      = HID_REQ_SetProtocol,
404
                                .wValue        = 1,
405
                                .wIndex        = HIDInterfaceInfo->State.InterfaceNumber,
406
                                .wLength       = 0,
407
                        };
408

    
409
                if ((ErrorCode = USB_Host_SendControlRequest(NULL)) != HOST_SENDCONTROL_Successful)
410
                  return ErrorCode;
411

    
412
                HIDInterfaceInfo->State.UsingBootProtocol = false;
413
        }
414

    
415
        if (HIDInterfaceInfo->Config.HIDParserData == NULL)
416
          return HID_ERROR_LOGICAL;
417

    
418
        if ((ErrorCode = USB_ProcessHIDReport(HIDReportData, HIDInterfaceInfo->State.HIDReportSize,
419
                                              HIDInterfaceInfo->Config.HIDParserData)) != HID_PARSE_Successful)
420
        {
421
                return HID_ERROR_LOGICAL | ErrorCode;
422
        }
423

    
424
        uint16_t LargestReportSizeBits = HIDInterfaceInfo->Config.HIDParserData->LargestReportSizeBits;
425
        HIDInterfaceInfo->State.LargestReportSize = (LargestReportSizeBits >> 3) + ((LargestReportSizeBits & 0x07) != 0);
426

    
427
        return 0;
428
}
429
#endif
430

    
431
#endif
432