summaryrefslogtreecommitdiff
path: root/digital/zigbit/bitcloud/stack/Components/HAL/drivers/USBClasses/DFU/src/dfuProtocol.c
blob: c19f312b964f7f75ee4bd5a16622252b5bdc323c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/****************************************************************************//**
  \file dfuProtocol.c

  \brief Implementation of Device firmware upgrade commands.

  \author
    Atmel Corporation: http://www.atmel.com \n
    Support email: avr@atmel.com

  Copyright (c) 2008-2011, Atmel Corporation. All rights reserved.
  Licensed under Atmel's Limited License Agreement (BitCloudTM).

  \internal
  History:
    08/09/11 N. Fomin - Created
*******************************************************************************/
/******************************************************************************
                   Includes section
******************************************************************************/
#include <dfuProtocol.h>
#include <usb.h>
#include <resetReason.h>
#include <halFlash.h>
#include <usbEnumeration.h>

/******************************************************************************
                   Define(s) section
******************************************************************************/
#define DFU_STATUS_OK               0x00
#define DFU_STATUS_MAX_POLL_TIMEOUT 0xFF
#define DFU_STATUS_NO_STRING        0x00

#define BOOTLOADER_FLAG_FLASH_OFFSET 5

/******************************************************************************
                   Global variables section
******************************************************************************/
static UsbDfuResponse_t dfuResponse;
static bool detachReceived = false;

/******************************************************************************
                   Implementations section
******************************************************************************/
/**************************************************************************//**
\brief EEPROM write callback.
******************************************************************************/
void dfuResetAction(void)
{
  HAL_WarmReset();
} 
/**************************************************************************//**
\brief DFU detach request handler.
******************************************************************************/
static void dfuDetach(void)
{ 
  uint8_t bootloaderFlag = 0x5A;
  HAL_EepromParams_t eepromParams = {
    .address = (FLASH_BOOTLOADER_PAGES + FLASH_EEPROM_PAGES) * IFLASH_BYTES_PER_PAGE -
               BOOTLOADER_FLAG_FLASH_OFFSET,
    .data = &bootloaderFlag,
    .length = 1
  };
  uint16_t page;
  
#if defined(AT91SAM7X256) || defined(AT91SAM3S4C)
  // Acknowledge the request
  sendZLP();
#endif

  detachReceived = true;

  halFlashPrepareForWrite();
  page = halFlashPreparePage(&eepromParams);
  halFlashWritePage(page, false);
  halFlashRestoreFromWrite();

  HAL_RegisterEndOfBusResetHandler(dfuResetAction);
}
/**************************************************************************//**
\brief DFU get status request handler.
******************************************************************************/
static void dfuGetStatus(void)
{ 
  uint8_t i = 2;

  dfuResponse.getStatusResponse.bStatus = DFU_STATUS_OK;
  while(i--)
    dfuResponse.getStatusResponse.bPollTimeout[i] = DFU_STATUS_MAX_POLL_TIMEOUT;
  dfuResponse.getStatusResponse.bState = detachReceived;
  dfuResponse.getStatusResponse.iString = DFU_STATUS_NO_STRING;

  HAL_UsbWrite(0, (void *)&dfuResponse, sizeof(DfuGetStatusResponse_t), NULL, NULL);
}

/**************************************************************************//**
\brief DFU get state request handler.
******************************************************************************/
static void dfuGetState(void)
{ 
  dfuResponse.getStateResponse.bState = detachReceived;

  HAL_UsbWrite(0, (void *)&dfuResponse, sizeof(DfuGetStateResponse_t), NULL, NULL);
}
/**************************************************************************//**
\brief Device firmware upgrade request handler.
\param[in]
  data - pointer to host's request.
******************************************************************************/
void dfuRequestHandler(uint8_t *data)
{
  UsbDfuRequest_t *pRequest = NULL;

  pRequest = (UsbDfuRequest_t *)data;
  if (NULL == pRequest)
    return;

  // Check request code
  switch (pRequest->request.bRequest)
  {
    case DFU_DETACH:
      dfuDetach();
      break;
    case DFU_GETSTATUS:
      dfuGetStatus();
      break;
    case DFU_GETSTATE:
      dfuGetState();
      break;
    default:
      HAL_Stall(0);
      break;
  }
}

//eof dfuProtocol.c