3 Copyright (C) Dean Camera, 2009.
5 dean [at] fourwalledcubicle [dot] com
6 www.fourwalledcubicle.com
10 Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
11 Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
13 Permission to use, copy, modify, and distribute this software
14 and its documentation for any purpose and without fee is hereby
15 granted, provided that the above copyright notice appear in all
16 copies and that both that the copyright notice and this
17 permission notice and warranty disclaimer appear in supporting
18 documentation, and that the name of the author not be used in
19 advertising or publicity pertaining to distribution of the
20 software without specific, written prior permission.
22 The author disclaim all warranties with regard to this
23 software, including all implied warranties of merchantability
24 and fitness. In no event shall the author be liable for any
25 special, indirect or consequential damages or any damages
26 whatsoever resulting from loss of use, data or profits, whether
27 in an action of contract, negligence or other tortious action,
28 arising out of or in connection with the use or performance of
34 * Main source file for the KeyboardMouse demo. This file contains the main tasks of the demo and
35 * is responsible for the initial application hardware configuration.
38 #include "KeyboardMouse.h"
40 /* Scheduler Task List */
43 { .Task
= USB_USBTask
, .TaskStatus
= TASK_STOP
},
44 { .Task
= USB_Mouse
, .TaskStatus
= TASK_RUN
},
45 { .Task
= USB_Keyboard
, .TaskStatus
= TASK_RUN
},
48 /* Global Variables */
49 /** Global structure to hold the current keyboard interface HID report, for transmission to the host */
50 USB_KeyboardReport_Data_t KeyboardReportData
;
52 /** Global structure to hold the current mouse interface HID report, for transmission to the host */
53 USB_MouseReport_Data_t MouseReportData
;
55 /** Main program entry point. This routine configures the hardware required by the application, then
56 * starts the scheduler to run the USB management task.
60 /* Disable watchdog if enabled by bootloader/fuses */
61 MCUSR
&= ~(1 << WDRF
);
64 /* Disable clock division */
65 clock_prescale_set(clock_div_1
);
67 /* Hardware Initialization */
71 /* Indicate USB not ready */
72 UpdateStatus(Status_USBNotReady
);
74 /* Initialize Scheduler so that it can be used */
77 /* Initialize USB Subsystem */
80 /* Scheduling - routine never returns, so put this last in the main function */
84 /** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
85 * starts the library USB task to begin the enumeration and USB management process.
87 EVENT_HANDLER(USB_Connect
)
89 /* Start USB management task */
90 Scheduler_SetTaskMode(USB_USBTask
, TASK_RUN
);
92 /* Indicate USB enumerating */
93 UpdateStatus(Status_USBEnumerating
);
96 /** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
97 * the status LEDs and stops the USB management task.
99 EVENT_HANDLER(USB_Disconnect
)
101 /* Stop running HID reporting and USB management tasks */
102 Scheduler_SetTaskMode(USB_USBTask
, TASK_STOP
);
104 /* Indicate USB not ready */
105 UpdateStatus(Status_USBNotReady
);
108 /** Event handler for the USB_ConfigurationChanged event. This is fired when the host sets the current configuration
109 * of the USB device after enumeration, and configures the keyboard and mouse device endpoints.
111 EVENT_HANDLER(USB_ConfigurationChanged
)
113 /* Setup Keyboard Report Endpoint */
114 Endpoint_ConfigureEndpoint(KEYBOARD_IN_EPNUM
, EP_TYPE_INTERRUPT
,
115 ENDPOINT_DIR_IN
, HID_EPSIZE
,
116 ENDPOINT_BANK_SINGLE
);
118 /* Setup Keyboard LED Report Endpoint */
119 Endpoint_ConfigureEndpoint(KEYBOARD_OUT_EPNUM
, EP_TYPE_INTERRUPT
,
120 ENDPOINT_DIR_OUT
, HID_EPSIZE
,
121 ENDPOINT_BANK_SINGLE
);
123 /* Setup Mouse Report Endpoint */
124 Endpoint_ConfigureEndpoint(MOUSE_IN_EPNUM
, EP_TYPE_INTERRUPT
,
125 ENDPOINT_DIR_IN
, HID_EPSIZE
,
126 ENDPOINT_BANK_SINGLE
);
128 /* Indicate USB connected and ready */
129 UpdateStatus(Status_USBReady
);
132 /** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
133 * control requests that are not handled internally by the USB library (including the HID commands, which are
134 * all issued via the control endpoint), so that they can be handled appropriately for the application.
136 EVENT_HANDLER(USB_UnhandledControlPacket
)
141 /* Handle HID Class specific requests */
142 switch (USB_ControlRequest
.bRequest
)
145 if (USB_ControlRequest
.bmRequestType
== (REQDIR_DEVICETOHOST
| REQTYPE_CLASS
| REQREC_INTERFACE
))
147 Endpoint_ClearSETUP();
149 /* Determine if it is the mouse or the keyboard data that is being requested */
150 if (!(USB_ControlRequest
.wIndex
))
152 ReportData
= (uint8_t*)&KeyboardReportData
;
153 ReportSize
= sizeof(KeyboardReportData
);
157 ReportData
= (uint8_t*)&MouseReportData
;
158 ReportSize
= sizeof(MouseReportData
);
161 /* Write the report data to the control endpoint */
162 Endpoint_Write_Control_Stream_LE(ReportData
, ReportSize
);
164 /* Clear the report data afterwards */
165 memset(ReportData
, 0, ReportSize
);
167 /* Finalize the stream transfer to send the last packet or clear the host abort */
173 if (USB_ControlRequest
.bmRequestType
== (REQDIR_HOSTTODEVICE
| REQTYPE_CLASS
| REQREC_INTERFACE
))
175 Endpoint_ClearSETUP();
177 /* Wait until the LED report has been sent by the host */
178 while (!(Endpoint_IsOUTReceived()));
180 /* Read in the LED report from the host */
181 uint8_t LEDStatus
= Endpoint_Read_Byte();
182 uint8_t LEDMask
= LEDS_LED2
;
184 if (LEDStatus
& 0x01) // NUM Lock
185 LEDMask
|= LEDS_LED1
;
187 if (LEDStatus
& 0x02) // CAPS Lock
188 LEDMask
|= LEDS_LED3
;
190 if (LEDStatus
& 0x04) // SCROLL Lock
191 LEDMask
|= LEDS_LED4
;
193 /* Set the status LEDs to the current HID LED status */
194 LEDs_SetAllLEDs(LEDMask
);
196 /* Clear the endpoint data */
199 /* Acknowledge status stage */
200 while (!(Endpoint_IsINReady()));
208 /** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
209 * log to a serial port, or anything else that is suitable for status updates.
211 * \param CurrentStatus Current status of the system, from the KeyboardMouse_StatusCodes_t enum
213 void UpdateStatus(uint8_t CurrentStatus
)
215 uint8_t LEDMask
= LEDS_NO_LEDS
;
217 /* Set the LED mask to the appropriate LED mask based on the given status code */
218 switch (CurrentStatus
)
220 case Status_USBNotReady
:
221 LEDMask
= (LEDS_LED1
);
223 case Status_USBEnumerating
:
224 LEDMask
= (LEDS_LED1
| LEDS_LED2
);
226 case Status_USBReady
:
227 LEDMask
= (LEDS_LED2
| LEDS_LED4
);
231 /* Set the board LEDs to the new LED mask */
232 LEDs_SetAllLEDs(LEDMask
);
235 /** Keyboard task. This generates the next keyboard HID report for the host, and transmits it via the
236 * keyboard IN endpoint when the host is ready for more data. Additionally, it processes host LED status
237 * reports sent to the device via the keyboard OUT reporting endpoint.
241 uint8_t JoyStatus_LCL
= Joystick_GetStatus();
243 /* Check if HWB is not pressed, if so mouse mode enabled */
244 if (!(HWB_GetStatus()))
246 if (JoyStatus_LCL
& JOY_UP
)
247 KeyboardReportData
.KeyCode
[0] = 0x04; // A
248 else if (JoyStatus_LCL
& JOY_DOWN
)
249 KeyboardReportData
.KeyCode
[0] = 0x05; // B
251 if (JoyStatus_LCL
& JOY_LEFT
)
252 KeyboardReportData
.KeyCode
[0] = 0x06; // C
253 else if (JoyStatus_LCL
& JOY_RIGHT
)
254 KeyboardReportData
.KeyCode
[0] = 0x07; // D
256 if (JoyStatus_LCL
& JOY_PRESS
)
257 KeyboardReportData
.KeyCode
[0] = 0x08; // E
260 /* Check if the USB system is connected to a host and report protocol mode is enabled */
263 /* Select the Keyboard Report Endpoint */
264 Endpoint_SelectEndpoint(KEYBOARD_IN_EPNUM
);
266 /* Check if Keyboard Endpoint Ready for Read/Write */
267 if (Endpoint_IsReadWriteAllowed())
269 /* Write Keyboard Report Data */
270 Endpoint_Write_Stream_LE(&KeyboardReportData
, sizeof(KeyboardReportData
));
272 /* Finalize the stream transfer to send the last packet */
275 /* Clear the report data afterwards */
276 memset(&KeyboardReportData
, 0, sizeof(KeyboardReportData
));
279 /* Select the Keyboard LED Report Endpoint */
280 Endpoint_SelectEndpoint(KEYBOARD_OUT_EPNUM
);
282 /* Check if Keyboard LED Endpoint Ready for Read/Write */
283 if (Endpoint_IsReadWriteAllowed())
285 /* Read in the LED report from the host */
286 uint8_t LEDStatus
= Endpoint_Read_Byte();
287 uint8_t LEDMask
= LEDS_LED2
;
289 if (LEDStatus
& 0x01) // NUM Lock
290 LEDMask
|= LEDS_LED1
;
292 if (LEDStatus
& 0x02) // CAPS Lock
293 LEDMask
|= LEDS_LED3
;
295 if (LEDStatus
& 0x04) // SCROLL Lock
296 LEDMask
|= LEDS_LED4
;
298 /* Set the status LEDs to the current Keyboard LED status */
299 LEDs_SetAllLEDs(LEDMask
);
301 /* Handshake the OUT Endpoint - clear endpoint and ready for next report */
307 /** Mouse task. This generates the next mouse HID report for the host, and transmits it via the
308 * mouse IN endpoint when the host is ready for more data.
312 uint8_t JoyStatus_LCL
= Joystick_GetStatus();
314 /* Check if HWB is pressed, if so mouse mode enabled */
317 if (JoyStatus_LCL
& JOY_UP
)
318 MouseReportData
.Y
= 1;
319 else if (JoyStatus_LCL
& JOY_DOWN
)
320 MouseReportData
.Y
= -1;
322 if (JoyStatus_LCL
& JOY_RIGHT
)
323 MouseReportData
.X
= 1;
324 else if (JoyStatus_LCL
& JOY_LEFT
)
325 MouseReportData
.X
= -1;
327 if (JoyStatus_LCL
& JOY_PRESS
)
328 MouseReportData
.Button
= (1 << 0);
331 /* Check if the USB system is connected to a host and report protocol mode is enabled */
334 /* Select the Mouse Report Endpoint */
335 Endpoint_SelectEndpoint(MOUSE_IN_EPNUM
);
337 /* Check if Mouse Endpoint Ready for Read/Write */
338 if (Endpoint_IsReadWriteAllowed())
340 /* Write Mouse Report Data */
341 Endpoint_Write_Stream_LE(&MouseReportData
, sizeof(MouseReportData
));
343 /* Finalize the stream transfer to send the last packet */
346 /* Clear the report data afterwards */
347 memset(&MouseReportData
, 0, sizeof(MouseReportData
));