00001 /* ---------------------------------------------------------------------------- */ 00002 /* Atmel Microcontroller Software Support */ 00003 /* SAM Software Package License */ 00004 /* ---------------------------------------------------------------------------- */ 00005 /* Copyright (c) 2015, Atmel Corporation */ 00006 /* */ 00007 /* All rights reserved. */ 00008 /* */ 00009 /* Redistribution and use in source and binary forms, with or without */ 00010 /* modification, are permitted provided that the following condition is met: */ 00011 /* */ 00012 /* - Redistributions of source code must retain the above copyright notice, */ 00013 /* this list of conditions and the disclaimer below. */ 00014 /* */ 00015 /* Atmel's name may not be used to endorse or promote products derived from */ 00016 /* this software without specific prior written permission. */ 00017 /* */ 00018 /* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR */ 00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */ 00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE */ 00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, */ 00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */ 00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */ 00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF */ 00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */ 00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */ 00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ 00028 /* ---------------------------------------------------------------------------- */ 00029 00030 /** \cond usb_iad_cdc_hid 00031 * \page usb_iad_cdc_hid USB CDC(Serial)+HID(Keyboard) Example 00032 * 00033 * \section Purpose 00034 * 00035 * The USB CDCHID Project will help you to get familiar with the 00036 * USB Device Port(UDP)interface .Also it can help you to be familiar with the USB 00037 * Framework that is used for rapid development of USB-compliant class 00038 * drivers such as USB Communication Device class (CDC), and how to combine 00039 * two USB functions to a single composite device (such as CDC + HID). 00040 * 00041 * \section Requirements 00042 * 00043 * This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board 00044 * that have UDP interface, depending on the functions included. 00045 * 00046 * \section win_drv_update Windows Driver Update 00047 * 00048 * The composite device is generally supported by Microsoft windows, but some 00049 * patches are needed for muti-interface functions such as CDC & Audio. 00050 * 00051 * \section Description 00052 * 00053 * This demo simulates a USB composite device that has USB Serial RS232 00054 * Converter and USB HID Keyboard functions. 00055 * 00056 * When the board running this program connected to a host (PC for example), with 00057 * USB cable, host will notice the attachment of a USB device. No device 00058 * driver offered for the device now. 00059 * 00060 * \section Usage 00061 * 00062 * -# Build the program and download it inside the board. 00063 * Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf 00064 * -# On the computer, open and configure a terminal application 00065 * (e.g. HyperTerminal on Microsoft Windows) with these settings: 00066 * - 115200 baud rate 00067 * - 8 bits of data 00068 * - No parity 00069 * - 1 stop bit 00070 * - No flow control 00071 * -# Start the application. 00072 * -# In the terminal window, the following text should appear: 00073 * \code 00074 * -- USB CDC HID Device Project xxx -- 00075 * -- SAMxxxxx-xx 00076 * -- Compiled: xxx xx xxxx xx:xx:xx -- 00077 * \endcode 00078 * -# When connecting USB cable to windows, the LED blinks, and the host 00079 * reports a new USB device attachment. 00080 * -# For the windows driver installation and the test functions, please 00081 * refer to "USB CDC serial converter" & 00082 * "USB HID Keyboard Project". 00083 * -# You can use the inf file 00084 * libraries\\usb\\device\\composite\\drv\\CompositeCDCSerial.inf 00085 * to install the CDC serial port. 00086 * 00087 * \section Reference 00088 * - usb_iad_cdc_hid/main.c 00089 * - pio: Pin configurations and peripheral configure. 00090 * - usb: USB Device Framework, USB CDC driver and UDP interface driver 00091 * - \ref usbd_framework 00092 * - \ref usbd_api 00093 * - \ref usbd_composite "composite" 00094 * - \ref usbd_composite_drv 00095 * - \ref usbd_hid "hid" \\ \ref usbd_hid_key "hid-keyboard" 00096 * - \ref usbd_hid_kbd_drv 00097 * - \ref usbd_cdc "cdc-serial" 00098 * - \ref usbd_cdc_serial_drv 00099 * - projects: 00100 * - \ref usb_hid_keyboard 00101 * - \ref usb_cdc_serial 00102 * 00103 */ 00104 00105 /** 00106 * \file 00107 * 00108 * This file contains all the specific code for the 00109 * usb_iad_cdc_hid project 00110 */ 00111 00112 /*---------------------------------------------------------------------------- 00113 * Headers 00114 *----------------------------------------------------------------------------*/ 00115 00116 #include "board.h" 00117 00118 #include <USBD_Config.h> 00119 #include <USBD_LEDs.h> 00120 00121 #include <CDCHIDDDriver.h> 00122 #include <CDCDSerial.h> 00123 #include <HIDDKeyboard.h> 00124 00125 #include <string.h> 00126 #include <stdbool.h> 00127 #include <stdint.h> 00128 #include <stdio.h> 00129 00130 /*--------------------------------------------------------------------------- 00131 * Definitions 00132 *---------------------------------------------------------------------------*/ 00133 #define NO_PUSHBUTTON 00134 /** Number of keys used in the example. */ 00135 #define NUM_KEYS 2 00136 00137 /** Number of non-modifiers keys. */ 00138 #define NUM_NORMAL_KEYS 1 00139 00140 /** Number of modifier keys. */ 00141 #define NUM_MODIFIER_KEYS (NUM_KEYS - NUM_NORMAL_KEYS) 00142 00143 /** NumLock LED index. */ 00144 #define LED_NUMLOCK USBD_LEDOTHER 00145 00146 /** Size in bytes of the packet used for reading data from USB */ 00147 #define DATAPACKETSIZE \ 00148 CHIP_USB_ENDPOINTS_MAXPACKETSIZE(CDCDSerialDriverDescriptors_DATAIN) 00149 00150 /** Size in bytes of the buffer used for reading data from the USB & USART */ 00151 #define DATABUFFERSIZE (DATAPACKETSIZE+2) 00152 00153 /*---------------------------------------------------------------------------- 00154 * External variables 00155 *----------------------------------------------------------------------------*/ 00156 00157 extern const USBDDriverDescriptors cdchiddDriverDescriptors; 00158 00159 /*--------------------------------------------------------------------------- 00160 * Internal variables 00161 *---------------------------------------------------------------------------*/ 00162 00163 /** Buffer for storing incoming USB data. */ 00164 COMPILER_ALIGNED(32) static unsigned char usbSerialBuffer0[DATABUFFERSIZE]; 00165 00166 /** Serial port opened */ 00167 static unsigned char isSerialPortON = 0; 00168 00169 /*- HID */ 00170 00171 #ifdef NO_PUSHBUTTON 00172 #else 00173 /** List of pinsPushButtons to configure for the application. */ 00174 static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS}; 00175 #endif 00176 00177 /** Array of key codes produced by each button. */ 00178 static uint8_t keyCodes[NUM_KEYS] = { 00179 HIDKeypad_A, 00180 HIDKeypad_NUMLOCK, 00181 }; 00182 00183 /** Current status (pressed or not) for each key. */ 00184 static uint8_t keyStatus[NUM_KEYS]; 00185 00186 /*----------------------------------------------------------------------------- 00187 * Callback re-implementation 00188 *-----------------------------------------------------------------------------*/ 00189 00190 00191 00192 /** 00193 * Invoked when the configuration of the device changes. Parse used endpoints. 00194 * \param cfgnum New configuration number. 00195 */ 00196 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum) 00197 { 00198 CDCHIDDDriver_ConfigurationChangedHandler(cfgnum); 00199 } 00200 00201 /** 00202 * Invoked when a new SETUP request is received from the host. Forwards the 00203 * request to the Mass Storage device driver handler function. 00204 * \param request Pointer to a USBGenericRequest instance. 00205 */ 00206 void USBDCallbacks_RequestReceived(const USBGenericRequest *request) 00207 { 00208 CDCHIDDDriver_RequestHandler(request); 00209 } 00210 00211 /*---------------------------------------------------------------------------- 00212 * Callbacks 00213 *----------------------------------------------------------------------------*/ 00214 00215 /** 00216 * Invoked when the CDC ControlLineState is changed 00217 * \param DTR New DTR value. 00218 * \param RTS New RTS value. 00219 */ 00220 void CDCDSerial_ControlLineStateChanged(uint8_t DTR, 00221 uint8_t RTS) 00222 { 00223 isSerialPortON = DTR; 00224 RTS = RTS; /* dummy */ 00225 } 00226 00227 /** 00228 * Invoked when the status of the keyboard LEDs changes. Turns the num. lock 00229 * LED on or off. 00230 * \param numLockStatus Indicates the current status of the num. lock key. 00231 * \param capsLockStatus Indicates the current status of the caps lock key. 00232 * \param scrollLockStatus Indicates the current status of the scroll lock key 00233 */ 00234 void HIDDKeyboardCallbacks_LedsChanged( 00235 uint8_t numLockStatus, 00236 uint8_t capsLockStatus, 00237 uint8_t scrollLockStatus) 00238 { 00239 capsLockStatus = capsLockStatus; 00240 scrollLockStatus = scrollLockStatus; 00241 00242 /* Num. lock */ 00243 if (numLockStatus) 00244 LED_Set(LED_NUMLOCK); 00245 else 00246 LED_Clear(LED_NUMLOCK); 00247 } 00248 00249 /*--------------------------------------------------------------------------- 00250 * Internal functions 00251 *---------------------------------------------------------------------------*/ 00252 00253 /** 00254 * Monitor keyboard buttons & Update key status in HID driver 00255 */ 00256 static void _HIDDKeyboardProcessKeys(void) 00257 { 00258 uint32_t i; 00259 uint8_t pressedKeys[NUM_KEYS]; 00260 uint8_t pressedKeysSize = 0; 00261 uint8_t releasedKeys[NUM_KEYS]; 00262 uint8_t releasedKeysSize = 0; 00263 00264 /* Monitor buttons */ 00265 #ifdef NO_PUSHBUTTON 00266 00267 if (DBG_IsRxReady()) { 00268 uint8_t key = DBG_GetChar(); 00269 00270 switch (key) { 00271 case '1': case '2': 00272 i = key - '1'; 00273 00274 if (keyStatus[i]) { 00275 /* Key press simulation */ 00276 TRACE_INFO("Key %u pressed\n\r", (unsigned int)i); 00277 keyStatus[i] = 0; 00278 pressedKeys[pressedKeysSize] = keyCodes[i]; 00279 pressedKeysSize ++; 00280 HIDDKeyboard_RemoteWakeUp(); 00281 } else { 00282 /* Key release simulation */ 00283 TRACE_INFO("Key %u released\n\r", (unsigned int)i); 00284 keyStatus[i] = 1; 00285 releasedKeys[releasedKeysSize] = keyCodes[i]; 00286 releasedKeysSize++; 00287 } 00288 00289 break; 00290 00291 default: DBG_PutChar(key); 00292 } 00293 } 00294 00295 #else 00296 00297 for (i = 0; i < PIO_LISTSIZE(pinsPushButtons); i++) { 00298 /* Check if button state has changed */ 00299 uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i])); 00300 00301 if (isButtonPressed != keyStatus[i]) { 00302 /* Update button state */ 00303 if (!isButtonPressed) { 00304 /* Key has been pressed */ 00305 TRACE_INFO("Key %u has been pressed\n\r", i); 00306 keyStatus[i] = 0; 00307 pressedKeys[pressedKeysSize] = keyCodes[i]; 00308 pressedKeysSize++; 00309 HIDDKeyboard_RemoteWakeUp(); 00310 } else { 00311 /* Key has been released */ 00312 TRACE_INFO("Key %u has been released\n\r", i); 00313 keyStatus[i] = 1; 00314 releasedKeys[releasedKeysSize] = keyCodes[i]; 00315 releasedKeysSize++; 00316 } 00317 } 00318 } 00319 00320 #endif 00321 00322 /* Update key status in the HID driver if necessary */ 00323 if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) { 00324 uint8_t status; 00325 00326 do { 00327 status = HIDDKeyboard_ChangeKeys(pressedKeys, 00328 pressedKeysSize, 00329 releasedKeys, 00330 releasedKeysSize); 00331 } while (status != USBD_STATUS_SUCCESS); 00332 } 00333 } 00334 00335 /** 00336 * Configure USBHS settings for USB device 00337 */ 00338 static void _ConfigureUotghs(void) 00339 { 00340 /* UTMI parallel mode, High/Full/Low Speed */ 00341 /* UUSBCK not used in this configuration (High Speed) */ 00342 PMC->PMC_SCDR = PMC_SCDR_USBCLK; 00343 /* USB clock register: USB Clock Input is UTMI PLL */ 00344 PMC->PMC_USB = PMC_USB_USBS; 00345 /* Enable peripheral clock for USBHS */ 00346 PMC_EnablePeripheral(ID_USBHS); 00347 USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE; 00348 /* Enable PLL 480 MHz */ 00349 PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF); 00350 00351 /* Wait that PLL is considered locked by the PMC */ 00352 while (!(PMC->PMC_SR & PMC_SR_LOCKU)); 00353 00354 /* IRQ */ 00355 NVIC_EnableIRQ(USBHS_IRQn); 00356 } 00357 00358 /*--------------------------------------------------------------------------- 00359 * Exported function 00360 *---------------------------------------------------------------------------*/ 00361 /** 00362 * Initializes drivers and start the USB CDCHID device. 00363 */ 00364 int main(void) 00365 { 00366 uint8_t usbConnected = 0, serialON = 0; 00367 00368 /* Disable watchdog */ 00369 WDT_Disable(WDT); 00370 00371 SCB_EnableICache(); 00372 SCB_EnableDCache(); 00373 00374 printf("-- USB CDC HID Device Project %s --\n\r", SOFTPACK_VERSION); 00375 printf("-- %s\n\r", BOARD_NAME); 00376 printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ , 00377 COMPILER_NAME); 00378 00379 /* If they are present, configure Vbus & Wake-up pins */ 00380 PIO_InitializeInterrupts(0); 00381 00382 /* If there is on board power, switch it off */ 00383 _ConfigureUotghs(); 00384 00385 /* ----- HID Function Initialize */ 00386 #ifdef NO_PUSHBUTTON 00387 printf("-- : DBG key 1 2 used as buttons\n\r"); 00388 printf("-- : 1st press to push, 2nd press to release\n\r"); 00389 #else 00390 /* Initialize key statuses and configure push buttons */ 00391 PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons)); 00392 #endif 00393 memset(keyStatus, 1, NUM_KEYS); 00394 00395 /* Configure LEDs */ 00396 LED_Configure(LED_NUMLOCK); 00397 00398 00399 /* USB CDCHID driver initialization */ 00400 CDCHIDDDriver_Initialize(&cdchiddDriverDescriptors); 00401 00402 /* connect if needed */ 00403 USBD_Connect(); 00404 00405 /* Driver loop */ 00406 while (1) { 00407 /* Device is not configured */ 00408 if (USBD_GetState() < USBD_STATE_CONFIGURED) { 00409 if (usbConnected) { 00410 printf("-I- USB Disconnect/Suspend\n\r"); 00411 usbConnected = 0; 00412 /* Serial port closed */ 00413 isSerialPortON = 0; 00414 } 00415 } else { 00416 if (usbConnected == 0) { 00417 printf("-I- USB Connect\n\r"); 00418 usbConnected = 1; 00419 } 00420 00421 if (!serialON && isSerialPortON) { 00422 printf("-I- SerialPort ON\n\r"); 00423 /* Start receiving data on the USB */ 00424 CDCDSerial_Read(usbSerialBuffer0, 00425 DATAPACKETSIZE, 00426 0, 00427 0); 00428 serialON = 1; 00429 } else if (serialON && !isSerialPortON) { 00430 printf("-I- SeriaoPort OFF\n\r"); 00431 serialON = 0; 00432 } 00433 00434 _HIDDKeyboardProcessKeys(); 00435 } 00436 } 00437 } 00438 /** \endcond */