[Tinyos-contrib-commits]
CVS: tinyos-1.x/contrib/imote2/tools/src/blrconsole/src
BinImageFile.c, NONE, 1.1 BinImageUpload.c, NONE,
1.1 CommandLine.c, NONE, 1.1 Makefile, NONE, 1.1 USBComm.c,
NONE, 1.1 USBMessageHandler.c, NONE, 1.1 main.c, NONE, 1.1
Lama Nachman
lnachman at users.sourceforge.net
Tue Oct 10 15:31:45 PDT 2006
Update of /cvsroot/tinyos/tinyos-1.x/contrib/imote2/tools/src/blrconsole/src
In directory sc8-pr-cvs10.sourceforge.net:/tmp/cvs-serv21513
Added Files:
BinImageFile.c BinImageUpload.c CommandLine.c Makefile
USBComm.c USBMessageHandler.c main.c
Log Message:
pushed out new release OCT 2006
--- NEW FILE: BinImageFile.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file BinImageFile.c
* @author Junaith Ahemed Shahabdeen
*
* The functions required for handling the binary image
* data are provided by this file. Some of the functions
* are opening the binary file and noting down the size
* of the image, reading the content of the image in to
* a buffer and providing utility functions to load code
* through USB.
*/
#include <BinImageFile.h>
#include <string.h>
#include <USBDefines.h>
FILE* bFile = NULL;
long FileSize = 0;
char* buffer;
/**
* Load_Binary_File
*
* This function loads the binary file which has
* to be transfered through USB in to memory.
*
* @param fname Name of the file that has to be loaded
*
* @return SUCCESS | FAIL
*/
result_t Load_Binary_File (char* fname)
{
bFile = fopen (fname, "rb" );
if (bFile==NULL)
{
fprintf (stderr, "Could not open the file %s \n", fname);
return FAIL;
}
// obtain file size.
fseek (bFile , 0 , SEEK_END);
FileSize = ftell (bFile);
rewind (bFile);
fprintf (stdout, "File Size %ld\n", FileSize);
buffer = (char*) malloc (FileSize);
if (buffer == NULL)
{
fprintf (stderr, "Error allocating memory to buffer\n");
return FAIL;
}
// copy the file into the buffer.
fread (buffer,1,FileSize,bFile);
// terminate
fclose (bFile);
return SUCCESS;
}
/**
* Get_BinFile_KBSize
*
* Return the file size in KB.
*
* @return file size
*
*/
long Get_BinFile_KBSize ()
{
return (FileSize/FILE_SIZE_DIVIDER);
}
/**
* Get_BinFile_Size
*
* Return the actual file size.
*
* @return file size.
*/
long Get_BinFile_Size ()
{
return (FileSize);
}
/**
* Get_Num_USB_Packets
*
* Returns the number of USB packets of size IMOTE_HID_SHORT_MAXPACKETDATA
* required to transfer the whole image.
*
* FIXME:
* If there are multiple motes and if there is a scenario where
* different files must be uploaded to each mote then this file
* has to keep track of the file name for each mote.
*
* @param nodeid The mote which is requesting the information. (Future Use)
*
* @return number of usb packets in the file.
*/
uint32_t Get_Num_USB_Packets (uint32_t nodeid)
{
if (FileSize % IMOTE_HID_SHORT_MAXPACKETDATA)
return ((uint32_t) (FileSize / IMOTE_HID_SHORT_MAXPACKETDATA)) + 1;
else
return ((uint32_t) (FileSize / IMOTE_HID_SHORT_MAXPACKETDATA));
return 0;
}
/**
* Get_Bin_Buffer_Data
*
* The function copies a fixed length from the starting index
* to the data pointer. The source of the data is the
* buffer in which the file is copied to.
*
* @param data Desitnation data pointer.
* @parma length Size to be copied from the main buffer.
* @param startindex Starting index in the main buffer.
*
* @return Size copied | 0 on error
*/
uint32_t Get_Bin_Buffer_Data (uint8_t* data, uint32_t length, uint32_t startindex)
{
uint32_t cpylen = 0;
if (startindex > FileSize)
return FAIL;
if ((startindex + length) > FileSize)
cpylen = (FileSize - startindex);
else
cpylen = length;
memcpy (data, buffer + startindex, cpylen);
return cpylen;
}
--- NEW FILE: BinImageUpload.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file BinImageUpload.c
* @author Junaith Ahemed Shahabdeen
*
* Provides the function required to upload code to IMote2.
*/
#include <BinImageUpload.h>
#include <CommandLine.h>
#include <USBDefines.h>
#include <Crc.h>
#include <windows.h>
#include <stdlib.h>
#include <sys/time.h>
/**
* After the whole image is downloaded the crc of the
* cumulative crc of the file in chunk size should be
* sent as a part of verify image.
*
* If there are many motes then this step has to be performed
* on the fly and the PC application has to remember which file
* was uploaded to the requesting mote.
*/
uint16_t Cumulative_Crc = 0;
/**
* Buffer Sent to the Mote
*/
uint8_t sendBuffer [BIN_DATA_WINDOW_SIZE * IMOTE_HID_SHORT_MAXPACKETDATA];
/**
* FIXME Used for flow control
*/
struct timeval now; /* time when we started waiting */
struct timespec timeout; /* timeout value for the wait function */
int done; /* are we done waiting? */
pthread_cond_t got_req = PTHREAD_COND_INITIALIZER;
pthread_mutex_t req_mutx = PTHREAD_MUTEX_INITIALIZER;
/**
* Binary_Code_Upload
*
* The binary chunk request from the Imote device is
* handled by this function. The reqest from the
* device provides the start index and the size
* of the chunk in of a given file that is being
* trasfered. The function breaks the buffer in to
* USB trasferable sizes and passes it to the USBComm
* module to be trasfered to the IMote.
*
* @param startpck Starting index denoted in number of USB Packets.
* @param numpck Number of packets to be transfered from start index.
*
* @return SUCCESS | FAIL
*/
result_t Binary_Code_Upload (uint32_t startpck, uint32_t numpck)
{
uint16_t numt = numpck; // Number of packets to be transfered
uint16_t numcnt = 1; // Local counter for keeping track of num pck.
uint32_t length = IMOTE_HID_SHORT_MAXPACKETDATA; // num bytes per packet.
uint32_t sindex = startpck * length; // Start index in the binary buffer.
uint32_t totlength = 0;
uint8_t data [length];
//uint16_t buffCrc = 0;
FILE *f;
/* create the file of 10 records */
f=fopen("testdump_org.bin","w");
//printf ("Request from Mote. Start = %ld, NumPck = %ld \n", startpck, numpck);
//printf ("Request for Binary Chunk. Number of packets requested = %ld\n", numpck);
got_req = PTHREAD_COND_INITIALIZER;
req_mutx = PTHREAD_MUTEX_INITIALIZER;
int rc = pthread_mutex_lock(&req_mutx);
if (rc)
{ /* an error has occurred */
perror("pthread_mutex_lock");
}
while (numcnt <= numt)
{
memset (data, 0xFF, IMOTE_HID_SHORT_MAXPACKETDATA);
if ((length = Get_Bin_Buffer_Data (data, IMOTE_HID_SHORT_MAXPACKETDATA, sindex)) != FAIL)
{
Send_Binary_Data (data, length, numcnt);
/**
* FIXME this is actually a lot of work. We know that we can only
* send 62 bytes per packet, but for the crc calculation it is
* absolutly required that we match with the IMOTE side. So let
* reform the whole chunk and calculate the CRC in the end.
*/
memcpy (sendBuffer + totlength, data, length);
if (f)
fwrite (sendBuffer + totlength, length, 1, f);
totlength += length;
sindex += length;
}
else
{
fprintf (stderr, "DIDNT GET DATA from Get_Bin_Buffer_Data \n");
/* lets get out of this while loop */
numt = numcnt - 1;
//return FAIL;
break;
}
++ numcnt;
}
fclose (f);
Cumulative_Crc = Crc_Buffer (sendBuffer, totlength, Cumulative_Crc);
//#ifdef DEBUG
if (!Is_Test_Program_Mode())
{
//#endif
Send_CRC_Command (sendBuffer, totlength, startpck, numpck);
//#ifdef DEBUG
}
else
{
uint16_t tstbuffCrc = 0;
tstbuffCrc = Crc_Buffer (sendBuffer, totlength, tstbuffCrc);
fprintf (stdout, "Send CRC Command now with following parameters; \n");
fprintf (stdout, "\t start = %ld \n\t num packet = %ld \n\t crc = %d\n",
startpck, numpck, tstbuffCrc);
}
//#endif
pthread_mutex_unlock(&req_mutx);
pthread_cond_destroy(&got_req);
return SUCCESS;
}
/**
* Send_Binary_Packet
*
* When the Mote request for one binary packet during the MMU Disabled mode,
* this function will send the right data from the file. The chunk size
* passed as parameter will identify the position in the file from which
* the data has to be copied.
*
* @param nseq Sequence number (Received from Device and has to be echoed)
* @param numpck Number of packets requested.
* @param ftpr The position in the file.
*
* @return SUCCESS | FAIL
*/
result_t Send_Binary_Packet (uint32_t nseq, uint32_t numpck, uint32_t fptr)
{
uint32_t length = IMOTE_HID_SHORT_MAXPACKETDATA; // num bytes per packet.
uint8_t data [length];
uint32_t sindex = fptr * length; // Start index in the binary buffer.
//fprintf (stdout, "Received Binary Packet Request %d - %d\n", nseq, fptr);
//memset (data, 0xFF, length);
if ((length = Get_Bin_Buffer_Data (data, length, sindex)) != FAIL)
{
Send_Binary_Data (data, length, nseq);
//Send_Binary_Data (data, IMOTE_HID_SHORT_MAXPACKETDATA, nseq);
memcpy (sendBuffer + ((nseq - 1) * IMOTE_HID_SHORT_MAXPACKETDATA), data, length);
}
else
{
fprintf (stderr, "DIDNT GET DATA from Get_Bin_Buffer_Data \n");
return FAIL;
}
/* Now we have reached the Buffer Limit. We have to send the CRC to the device*/
if ((!(nseq % BIN_DATA_WINDOW_SIZE)) || (fptr >= (Get_Num_USB_Packets (0) - 1)))
{
Sleep (3);
//printf ("Finished uploading the chunk.\n");
Cumulative_Crc = Crc_Buffer (sendBuffer, (nseq*IMOTE_HID_SHORT_MAXPACKETDATA), Cumulative_Crc);
Send_CRC_Command (sendBuffer, (nseq*IMOTE_HID_SHORT_MAXPACKETDATA), 0,0);
}
return SUCCESS;
}
/**
* Send_Image_Crc_Command
*
* After the whole image is downloaded the crc of the
* cumulative crc of the file in chunk size should be
* sent as a part of verify image.
*
* @return SUCCESS | FAIL
*/
result_t Send_Image_Crc_Command ()
{
CmdCrcData crcdata;
uint16_t cumulative_crc = 0;
uint32_t length = 0;
uint32_t sindex = 0;
uint32_t Size=(uint32_t)(Get_BinFile_Size());
uint32_t CSize=(uint32_t)(BIN_DATA_WINDOW_SIZE * IMOTE_HID_SHORT_MAXPACKETDATA);
uint32_t RSize = 0;
uint32_t CurSize = 0;
while (CurSize < Size)
{
RSize = ((Size - CurSize) > CSize)? CSize : (Size - CurSize);
memset (sendBuffer, 0x0, CSize);
if ((length = Get_Bin_Buffer_Data (sendBuffer, RSize, sindex)) != FAIL)
{
cumulative_crc = Crc_Buffer (sendBuffer, length, cumulative_crc);
CurSize += RSize;
sindex += RSize;
}
else
{
fprintf (stderr, "Error Receiving File Data \n");
return FAIL;
}
}
crcdata.chunkStart = 0;
crcdata.NumUSBPck = Get_Num_USB_Packets (0);
crcdata.ChunkCRC = cumulative_crc;
Send_USB_Command_Packet (RSP_CRC_CHECK, sizeof (CmdCrcData), &crcdata);
printf ("CRC of the Image = %d, Total Size = %ld\n", cumulative_crc, Size);
Cumulative_Crc = 0;
return SUCCESS;
}
/**
* Send_CRC_Command
*
* The function calculates the CRC of a buffer of given length
* and sends the result to the mote over USB.
*
* @param buff The buffer for which crc must be computed.
* @param length Length of the buffer.
*
* @return SUCCESS | FAIL
*/
result_t Send_CRC_Command (uint8_t* buff, uint32_t length,
uint32_t startpck, uint32_t numt)
{
uint16_t tstbuffCrc = 0;
USBCommand* cmd;
CmdCrcData* crcdata;
uint32_t len = sizeof (USBCommand) + sizeof (CmdCrcData);
cmd = (USBCommand*) malloc (len);
tstbuffCrc = Crc_Buffer (buff, length, tstbuffCrc);
if (cmd != NULL)
{
cmd->type = RSP_CRC_CHECK;
crcdata = (CmdCrcData*) cmd->data;
crcdata->chunkStart = startpck;
crcdata->NumUSBPck = numt;
crcdata->ChunkCRC = tstbuffCrc;
Send_USB_Command (cmd, len);
printf ("Sending CRC Check command %d\n", tstbuffCrc);
free (cmd);
}
return SUCCESS;
}
/**
* Send_Test_CRC_Command
*
* This function is used in the debug mode to send
* crc command to the mote. (allows to fake crc)
*
* @param startpck
* @param numt
* @param crc
*
* @return SUCCESS | FAIL
*/
result_t Send_Test_CRC_Command (uint32_t startpck, uint32_t numt, uint16_t crc)
{
CmdCrcData crcdata;
crcdata.chunkStart = startpck;
crcdata.NumUSBPck = numt;
crcdata.ChunkCRC = crc;
printf ("Sending CRC Command.\n");
Send_USB_Command_Packet (RSP_CRC_CHECK, sizeof (CmdCrcData), &crcdata);
return SUCCESS;
}
--- NEW FILE: CommandLine.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file CommandLine.c
* @author Junaith Ahemed Shahabdeen
*
* The file provides the command line interface for the
* -c option. The command line is a seprate thread.
*/
#include <CommandLine.h>
#include <AttrAccess.h>
#include <USBMessageHandler.h>
#include <BinImageUpload.h>
//#ifdef DEBUG
#include <BinImageFile.h>
//#endif
#define CMD_SIZE 256
#define MAX_ARGS 10
/**
* print_command_help
*
* Displays help menu for the user with different commands
* and its parameters. The second section provides the
* name of the attributes and a short description about each
* attribute.
*/
void print_command_help ()
{
printf ("Command [Options]\n");
printf ("Command and Options:\n");
printf ("\tgetattr: Attribute_Name\n");
printf ("\t\tRequest the value of an attribute from the attribute table.\n");
printf ("\t\tThe command dumps the attribute to the stdout.\n");
printf ("\tsetattr: Attribute_Name Attribute_Value\n");
printf ("\t\tSet a new value to an attribute in the attribute table.\n");
printf ("\t\tThe command returns SUCCESS or ERROR to stdout.\n");
printf ("\tdumpflash:\n");
printf ("\t\tReads the uploaded code from the Secondary location\n");
printf ("\t\tin flash and dumps it to a file (flashdump.bin).\n");
printf ("\t\tThe command is mostly used for upload verification\n");
printf ("\t\tpurpose.\n");
printf ("\tloadcode:\n");
printf ("\t\tIf the application is started with (-tp) option,\n");
printf ("\t\tthen this command will place the device in Code\n");
printf ("\t\tLoad mode.\n");
printf ("\timagedetail:\n");
printf ("\t\tSend image details to the device while in test \n");
printf ("\t\tprogram mode, that is if the application is started \n");
printf ("\t\twith -tp option.\n");
printf ("\tsendbindata:\n");
printf ("\t\tSend the next binary chunk to the device. This command\n");
printf ("\t\tis only valid during test program mode.\n");
printf ("\tcrc:\n");
printf ("\t\tSend crc of the current uploaded chunk. This Command\n");
printf ("\t\tis only valid during test program mode.\n");
printf ("\n");
printf ("\n");
printf ("Attribute List:\n");
printf ("\tBLR_TABLE - Address of BootLoader Table.\n");
printf ("\tSHARED_TABLE - Address of Shared Table (app and boot loader).\n");
printf ("\tSYNC_TOUT - Initial PC Sync Timeout.\n");
printf ("\tCMD_RETRY - Number of retries for command failures.\n");
printf ("\tCRC_RETRY - Number of retries for CRC failues.\n");
printf ("\tCMD_TOUT - Timeout Value for Commands (retries).\n");
printf ("\tBIN_TOUT - Timeout Value for Binary Chunk (retries).\n");
printf ("\tST_TOUT - Timeout Value for Self Test (Watch Dog).\n");
printf ("\tPIMG_LOC - Primary or Golden Image Location.\n");
printf ("\tPIMG_CRC - Crc of the image loaded in primary location.\n");
printf ("\tPIMG_SIZE - Size of the image loaded in primary location.\n");
printf ("\tSIMG_LOC - Secondary Image Location.\n");
printf ("\tSIMG_CRC - Crc of the image loaded in secondary location.\n");
printf ("\tSIMG_SIZE - Size of the image loaded in secondary location.\n");
printf ("\tBIMG_CRC - Crc of the Image in boot location. Must be \n");
printf ("\t\t\tequal to the crc of the primary image.\n");
printf ("\tBIMG_SIZE - Size of the image at boot location. Must be \n");
printf ("\t\t\tequal to the size of the primary image.\n");
printf ("\tVER_IMG - TRUE or FALSE. When set to true the boot loader\n");
printf ("\t\t\twill verify the secondary image and will make\n");
printf ("\t\t\tit as the current golden image.\n");
printf ("\tSELF_TEST - TRUE or FALSE value. When set to true the\n");
printf ("\t\t\tboot loader prepares the secondary image for self test\n");
printf ("\t\t\tand load it to boot location. After the Self Test is\n");
printf ("\t\t\tcompleted the boot loader validates it and decides if\n");
printf ("\t\t\tthe new image should be marked as golden.\n");
printf ("\tSTD_IMG_LOC - Default Self_Test Image Location.\n");
printf ("\tSTD_IMG_CRC - Crc of the image loaded in default Self Test location.\n");
printf ("\tSTD_IMG_SIZE - Size of the image loaded in default Self Test location.\n");
printf ("\tST_IMG_LOC - Self_Test Image Location for Application.\n");
printf ("\tST_IMG_CRC - Crc of the image loaded in App Self Test location.\n");
printf ("\tST_IMG_SIZE - Size of the image loaded in App Self Test location.\n");
printf ("\t\n");
printf ("\t\t\n");
}
/**
* Command_Line
*
* The Command line interface for the application. This
* function will wait for a command from the user, once received
* it will process the command and take the necessary steps.
* It also provides a help menu which explains the available
* commands and how to use those commands.
* This function is invoked as a seperate thread.
*/
void* Command_Line ()
{
unsigned char tmpbuff [CMD_SIZE];
unsigned char buff [CMD_SIZE];
unsigned char buff1;
unsigned char cargs [MAX_ARGS][CMD_SIZE];
unsigned char* arg;
unsigned int argc = 1;
unsigned int numbytes = 0;
while (1)
{
numbytes = 0;
memset (buff, 0, CMD_SIZE);
printf ("Command > ");
/**
* The command line interface in cygwin is really bad.
* Its easy to mess up the display. I had to go through all this
* pain to prevent it as much as possible.
*/
while (1)
{
buff1 = getc (stdin);
if (buff1 == 27) /* Check if its an escape charecter*/
{ /* If so then dump the next 2 charecters*/
getc (stdin);
buff1 = getc (stdin);
if ((buff1) == 65) printf ("\n"); /*UpArrow, compensate with end lines*/
}
else if (buff1 == 8) /*Back Space so delete a charecter*/
{
if (numbytes > 0)
--numbytes;
}
else if (buff1 == 10) /* End line break out of the while loop to process*/
break;
else
{
tmpbuff [numbytes] = buff1;
++numbytes;
}
}
//if (skipLines > 0)
//while (gets (buff) == NULL) {}
pthread_testcancel ();
//if (strcmp (buff, "\n") > 0)
if (numbytes > 0)
{
memcpy (buff, tmpbuff, numbytes);
arg = strtok (buff, " ");
strcpy (cargs [0], arg);
for (argc=1; argc < MAX_ARGS; argc++)
{
if ((arg = strtok (NULL, " ")) == NULL)
break;
else
strcpy (cargs [argc], arg);
}
//printf ("\t %d %s \n ", argc, cargs [0]);
if (strcmp (cargs [0], "exit") == 0)
{
exit (0);
}
else if (strcmp (cargs [0], "getattr") == 0)
{
if (argc >= 2)
Handle_Get_Attribute (cargs [1]);
else
{
fprintf (stderr, "getattr requires atlease 1 argument\n");
print_command_help ();
}
}
else if (strcmp (cargs [0], "setattr") == 0)
{
if (argc >= 3)
Handle_Set_Attribute (cargs[1], cargs[2]);
else
{
fprintf (stderr, "setattr requires atlease 2 argument\n");
print_command_help ();
}
}
else if (strcmp (cargs[0], "dumpflash") == 0)
{
Dump_From_Flash (0, 0);
}
else if (strcmp (cargs[0], "crc") == 0)
{
if (argc >= 2)
Handle_Send_Crc ("0", "0", cargs[1]);
else
{
fprintf (stderr,"The crc command requires atleast 3 arguments\n");
print_command_help ();
}
}
else if (strcmp (cargs[0], "loadcode") == 0)
{
uint8_t imgtyp = APPLICATION;
if (Send_USB_Command_Packet (RSP_USB_CODE_LOAD, 1, &imgtyp) == FAIL)
fprintf (stderr, "Could not place the Device in upload mode\n");
}
else if (strcmp (cargs[0], "imagedetail") == 0)
{
RspImageDetail imgdetail;
uint8_t Length = sizeof(RspImageDetail);
imgdetail.ImageSize = (uint32_t)Get_BinFile_Size ();
imgdetail.NumUSBPck = (uint32_t)Get_Num_USB_Packets (0);
Send_USB_Command_Packet (RSP_GET_IMAGE_DETAILS, Length, (void*)&imgdetail);
fprintf (stdout, "GET_IMAGE_DETAILS Received.ImgSize=%ld\n", imgdetail.NumUSBPck);
}
else if (strcmp (cargs[0], "sendbindata") == 0)
{
Dbg_Binary_Code_Upload ();
}
else if (strcmp (cargs[0], "reboot") == 0)
{
}
else if (strcmp (cargs[0], "help") == 0)
print_command_help ();
else if (strcmp (cargs[0], "memtest") == 0)
{
Send_USB_Command_Packet (RSP_FLASH_MEM_TEST, 0, NULL);
}
else
{
fprintf (stderr, "Unknown Command: %s. Ignored.\n",cargs[0]);
}
memset (cargs [0], 0, CMD_SIZE);
}
}
}
/**
* Handle_Get_Attribute
*
* Checks the arguments passed to the getattr command and
* sends a Get_Attribute command to the mote with appropriate
* attribute type.
*
*/
result_t Handle_Get_Attribute (char* args)
{
uint8_t buff [62];
USBCommand* cmd;
Attribute* attr;
cmd = (USBCommand*) buff;
cmd->type = RSP_GET_ATTRIBUTE;
attr = (Attribute*) cmd->data;
if (strcmp (args, "BLR_TABLE") == 0)
attr->AttrType = BL_ATTR_TYP_BOOTLOADER;
else if (strcmp (args, "SHARED_TABLE") == 0)
attr->AttrType = BL_ATTR_TYP_SHARED;
else if (strcmp (args, "SYNC_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_SYNC_TIMEOUT;
else if (strcmp (args, "CMD_RETRY") == 0)
attr->AttrType = BL_ATTR_TYP_CMD_FAIL_RETRY;
else if (strcmp (args, "CRC_RETRY") == 0)
attr->AttrType = BL_ATTR_TYP_CRC_FAIL_RETRY;
else if (strcmp (args, "CMD_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_CMD_TIMEOUT;
else if (strcmp (args, "BIN_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_BIN_TIMEOUT;
else if (strcmp (args, "ST_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_SELF_TEST_TIMEOUT;
else if (strcmp (args, "PIMG_LOC") == 0)
attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_LOCATION;
else if (strcmp (args, "PIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_CRC;
else if (strcmp (args, "PIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_SIZE;
else if (strcmp (args, "SIMG_LOC") == 0)
attr->AttrType = BL_ATTR_TYP_SECONDARY_IMG_LOCATION;
else if (strcmp (args, "SIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_SECONDARY_IMG_CRC;
else if (strcmp (args, "SIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_SECONDARY_IMG_SIZE;
else if (strcmp (args, "VER_IMG") == 0)
attr->AttrType = ATTR_VERIFY_IMAGE;
else if (strcmp (args, "SELF_TEST") == 0)
attr->AttrType = ATTR_PERFORM_SELF_TEST;
else if (strcmp (args, "BIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_BOOT_IMG_CRC;
else if (strcmp (args, "BIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_BOOT_IMG_SIZE;
else if (strcmp (args, "STD_IMG_LOC") == 0)
attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_LOC;
else if (strcmp (args, "STD_IMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_CRC;
else if (strcmp (args, "STD_IMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_SIZE;
else if (strcmp (args, "ST_IMG_LOC") == 0)
attr->AttrType = ATTR_SELF_TEST_IMG_LOC;
else if (strcmp (args, "ST_IMG_CRC") == 0)
attr->AttrType = ATTR_SELF_TEST_IMG_CRC;
else if (strcmp (args, "ST_IMG_SIZE") == 0)
attr->AttrType = ATTR_SELF_TEST_IMG_SIZE;
else if (strcmp (args, "BSTATE") == 0)
attr->AttrType = BL_ATTR_TYP_BOOTLOADER_STATE;
else
{
fprintf (stderr, "Requesting Unknown Attribute %s\n",args);
return FAIL;
}
Send_USB_Command (cmd, sizeof(USBCommand) + sizeof (Attribute));
return SUCCESS;
}
/**
* Handle_Set_Attribute
*
* Checks the arguments passed to the setattr command and
* sends a Set_Attribute command to the mote with appropriate
* attribute type and value.
*
*/
result_t Handle_Set_Attribute (char* args1, char* args2)
{
uint8_t buff [62];
Attribute* attr;
//uint32_t val = (uint32_t) atoi (args2);
uint32_t val = (uint32_t) strtoul (args2, (char**)NULL, 10);
attr = (Attribute*) buff;
//cmd->type = RSP_SET_ATTRIBUTE;
if (strcmp (args1, "SYNC_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_SYNC_TIMEOUT;
else if (strcmp (args1, "CMD_RETRY") == 0)
attr->AttrType = BL_ATTR_TYP_CMD_FAIL_RETRY;
else if (strcmp (args1, "CRC_RETRY") == 0)
attr->AttrType = BL_ATTR_TYP_CRC_FAIL_RETRY;
else if (strcmp (args1, "CMD_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_CMD_TIMEOUT;
else if (strcmp (args1, "BIN_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_BIN_TIMEOUT;
else if (strcmp (args1, "ST_TOUT") == 0)
attr->AttrType = BL_ATTR_TYP_SELF_TEST_TIMEOUT;
//else if (strcmp (args1, "PIMG_LOC") == 0)
// attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_LOCATION;
else if (strcmp (args1, "VER_IMG") == 0)
attr->AttrType = ATTR_VERIFY_IMAGE;
else if (strcmp (args1, "SELF_TEST") == 0)
attr->AttrType = ATTR_PERFORM_SELF_TEST;
else if (strcmp (args1, "PIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_CRC;
else if (strcmp (args1, "PIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_PRIMARY_IMG_SIZE;
else if (strcmp (args1, "SIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_SECONDARY_IMG_CRC;
else if (strcmp (args1, "SIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_SECONDARY_IMG_SIZE;
else if (strcmp (args1, "BIMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_BOOT_IMG_CRC;
else if (strcmp (args1, "BIMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_BOOT_IMG_SIZE;
//else if (strcmp (args1, "STD_IMG_LOC") == 0)
// attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_LOC;
else if (strcmp (args1, "STD_IMG_CRC") == 0)
attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_CRC;
else if (strcmp (args1, "STD_IMG_SIZE") == 0)
attr->AttrType = BL_ATTR_TYP_DEF_SELF_TEST_IMG_SIZE;
//else if (strcmp (args1, "ST_IMG_LOC") == 0)
// attr->AttrType = ATTR_SELF_TEST_IMG_LOC;
else if (strcmp (args1, "ST_IMG_CRC") == 0)
attr->AttrType = ATTR_SELF_TEST_IMG_CRC;
else if (strcmp (args1, "ST_IMG_SIZE") == 0)
attr->AttrType = ATTR_SELF_TEST_IMG_SIZE;
else
{
fprintf (stderr, "Cannot Set Attribute %s.\n",args1);
return FAIL;
}
attr->AttrLength = 4;
memcpy (&attr->AttrValue, &val, 4);
Send_USB_Command_Packet (RSP_SET_ATTRIBUTE,
sizeof (Attribute) + attr->AttrLength, buff);
//Send_USB_Command (cmd, sizeof(USBCommand) + sizeof (Attribute));
return SUCCESS;
}
/**
* Handle_Send_Crc
*
* Sends a crc command to the mote. The buffer starting and the
* number of usb packets in the buffer must be passed as a
* parameter to the function together with the CRC.
* NOTE:
* This command provides a way to see if the CRC check
* works and also validate if the boot loader is re-requesting
* the same buffer when a failure occurs. If the application is
* invoked in TestProgram mode the the correct CRC will
* be printed to the screen after every chunk is uploaded.
*
* @param arg1
* @param arg2
* @param arg3
*
* @return SUCCESS | FAIL
*/
result_t Handle_Send_Crc (char* arg1, char* arg2, char* arg3)
{
uint32_t start = atoi(arg1);
uint32_t numpck = atoi(arg2);
uint32_t crc = atoi(arg3);
fprintf (stdout, " %d %d \n", atoi(arg1), atoi(arg2));
Send_Test_CRC_Command (start, numpck, crc);
return SUCCESS;
}
--- NEW FILE: Makefile ---
#
# Author Junaith Ahemed Shahabdeen
#
#
#
INCLUDES = -I../include \
-I/usr/include/w32api/ddk/ \
-I/usr/include/w32api/ \
-I../include/ddk/ \
-I../../bootloader/include \
-I../../bootloader/blinclude
# -static -nostdlib
CC = gcc
CFLAGS = -c -g -Wall
LIBFLAGS = -lsetupapi -lhid # -luser32 -lkernel32
BUILD_DIR=build
BL_SOURCES = \
USBComm.c \
USBMessageHandler.c \
BinImageFile.c \
BinImageUpload.c \
CommandLine.c \
main.c
###
# External Source that we are using. Usually
# code from the bootloader.
###
BL_SOURCES += ../../bootloader/src/Crc.c
BL_LDFLAGS = \
-Wl,-Map,pc-app.map
EXEC=$(BUILD_DIR)/USBLoaderHost.exe
DISASSEM=$(BUILD_DIR)/disassemble.S
CLEANFILES = *~ \
*.o \
*.map \
BL_OBJS = $(BL_SOURCES:.c=.o)
all: $(BUILD_DIR) $(BL_ASM_SRC) $(BL_SOURCES) $(EXEC) $(BIN)
$(BIN): $(EXEC)
xscale-elf-objdump -S $(EXEC) > $(DISASSEM)
$(BUILD_DIR):
mkdir -p $(BUILD_DIR)
$(EXEC): $(BL_OBJS)
$(CC) $(BL_LDFLAGS) $(INCLUDES) $(BL_OBJS) $(LIBFLAGS) -o $@
mv -f $(BL_OBJS) *.map $(BUILD_DIR)
.c.o:
$(CC) $(CFLAGS) $(INCLUDES) $< -o $@
clean:
rm -f $(CLEANFILES)
rm -rf $(BUILD_DIR)
--- NEW FILE: USBComm.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file USBComm.c
* @author Junaith Ahemed Shahabdeen
*
* This modules communicates with the USB driver to send and
* receive packets. It also provides functions to search
* through a list of USB devices of a specific class and
* set up an overlapped I/O communication with those devices.
* The file uses lot of inbuilt function of the HID class defined
* in the windowsDDK, the usage of each function is explained when
* required.
*/
#include <USBComm.h>
#include <USBMessageHandler.h>
#define vID 0x042b
#define pID 0x1337
GUID HidGuid;
HDEVINFO hDevInfo;
unsigned long Required;
BOOLEAN MyDeviceDetected = FALSE;
HANDLE DeviceHandle;
OVERLAPPED hRxEventObj;
OVERLAPPED hTxEventObj;
OVERLAPPED HIDOverlapped;
char OutputReport[256];
char InputReport[256];
DWORD NumberOfBytesRead;
DWORD Length = 0;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
HIDP_CAPS Capabilities;
/**
* USB_Init
*
* Intialize the USB Handle and clear the events and open the USB
* handle for communication by calling the <B>Open_Imote_HID</B> function.
*
* @return SUCCESS | FAIL
*/
result_t USB_Init ()
{
int ret = FAIL;
DeviceHandle = INVALID_HANDLE_VALUE;
hRxEventObj.hEvent = INVALID_HANDLE_VALUE;
hTxEventObj.hEvent = INVALID_HANDLE_VALUE;
hRxEventObj.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
hTxEventObj.hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
if (Open_Imote_HID ())
ret = SUCCESS;
return ret;
}
/**
* Open_Imote_HID
*
* The function opens the USB communication handle to the IMote. I browses
* through the list of members in the HID class from windows and identifies
* the deivces of interest using the PID and the VID.
*
* <B>HidD_GetHidGuid</B> gets the GUID for all system HIDs and returns the
* GUID in HidGuid.
*
* <B>SetupDiGetClassDevs</B> returns a handle to a device information set for
* all installed devices. It requires the GUID returned by GetHidGuid.
*
* <B>SetupDiEnumDeviceInterfaces</B>, On return, MyDeviceInterfaceData contains
* the handle to SP_DEVICE_INTERFACE_DATA structure for a detected device. The
* function requires the DeviceInfoSet returned in SetupDiGetClassDevs, the
* HidGuid returned in GetHidGuid and an index to specify a device.
*
* <B>SetupDiGetDeviceInterfaceDetail</B> returns a SP_DEVICE_INTERFACE_DETAIL_DATA
* structure containing information about a device. To retrieve the information,
* call this function twice. The first time returns the size of the structure in
* Length. The second time returns a pointer to the data in DeviceInfoSet. It
* requires a DeviceInfoSet returned by SetupDiGetClassDevs the
* SP_DEVICE_INTERFACE_DATA structure returned by SetupDiEnumDeviceInterfaces.
* The final parameter is an optional pointer to an SP_DEV_INFO_DATA structure.
* This application doesn't retrieve or use the structure. If retrieving the
* structure, set MyDeviceInfoData.cbSize = length of MyDeviceInfoData. and pass
* the structure's address.
*
* <B>CreateFile</B> returns a handle that enables reading and writing to the
* device. It requires the DevicePath in the detailData structure returned by
* SetupDiGetDeviceInterfaceDetail.
*
* <B>HidD_GetAttributes</B> requests information from the device. It requires
* the handle returned by CreateFile and returns a HIDD_ATTRIBUTES structure
* containing the Vendor ID, Product ID, and Product Version Number. Use this
* information to decide if the detected device is the one we're looking for.
*
* @return SUCCESS | FAIL
*/
result_t Open_Imote_HID()
{
//Use a series of API calls to find a HID with a specified Vendor IF and
//Product ID.
HIDD_ATTRIBUTES Attributes;
SP_DEVICE_INTERFACE_DATA devInfoData;
BOOLEAN LastDevice = FALSE;
int MemberIndex = 0;
LONG Result;
Length = 0;
detailData = NULL;
DeviceHandle=NULL;
HidD_GetHidGuid(&HidGuid);
hDevInfo=SetupDiGetClassDevs (&HidGuid, NULL, NULL,
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
devInfoData.cbSize = sizeof(devInfoData);
//Step through the available devices looking for the one we want. Quit on
//detecting the desired device or checking all available devices without
//success.
MemberIndex = 0;
LastDevice = FALSE;
do
{
Result=SetupDiEnumDeviceInterfaces (hDevInfo, 0, &HidGuid,
MemberIndex, &devInfoData);
if (Result != 0)
{
//A device has been detected, so get more information about it.
//Get the Length value.
//The call will return with a "buffer too small" error which can be ignored.
Result = SetupDiGetDeviceInterfaceDetail (hDevInfo, &devInfoData,
NULL, 0, &Length, NULL);
//Allocate memory for the hDevInfo structure, using the returned Length.
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
//Set cbSize in the detailData structure.
detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//Call the function again, this time passing it the returned buffer size.
Result = SetupDiGetDeviceInterfaceDetail (hDevInfo, &devInfoData,
detailData, Length, &Required, NULL);
// Open a handle to the device.
// To enable retrieving information about a system mouse or keyboard,
// don't request Read or Write access for this handle.
DeviceHandle=CreateFile (detailData->DevicePath,
GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
//printf ("The Last Error = %lx\n", GetLastError());
//Set the Size to the number of bytes in the structure.
Attributes.Size = sizeof(Attributes);
Result = HidD_GetAttributes (DeviceHandle, &Attributes);
//printf("The Last Error = %ld\n", GetLastError());
//Is it the desired device?
MyDeviceDetected = FALSE;
if (Attributes.VendorID == vID)
{
if (Attributes.ProductID == pID)
{
MyDeviceDetected = TRUE;
Get_Device_Capabilities();
//Register the Device to detect if the device is attached or removed.
Register_For_Device_Notifications (HidGuid);
}
else
//The Product ID doesn't match.
CloseHandle(DeviceHandle);
}
else
//The Vendor ID doesn't match.
CloseHandle(DeviceHandle);
free(detailData);
}
else
LastDevice=TRUE;
MemberIndex = MemberIndex + 1;
} while ((LastDevice == FALSE) && (MyDeviceDetected == FALSE));
if (MyDeviceDetected == FALSE)
printf ("Device not detected\n");
else
printf ("Device detected\n");
SetupDiDestroyDeviceInfoList (hDevInfo);
//printf("The Last Error = %s\n", GetLastError());
return MyDeviceDetected;
}
/**
* Get_Device_Capabilities
*
* <B>HidD_GetPreparsedData</B> returns a pointer to a buffer containing
* the information about the device's capabilities. It requires a handle
* returned by CreateFile. There's no need to access the buffer directly, but
* HidP_GetCaps and other API functions require a pointer to the buffer.
*
* <B>HidP_GetCaps</B> Learn the device's capabilities.For standard devices
* such as joysticks, you can find out the specific capabilities of the device.
* For a custom device, the software will probably know what the device is
* capable of, and the call only verifies the information. It requires the
* pointer to the buffer returned by HidD_GetPreparsedData and returns a
* Capabilities structure containing the information.
*/
void Get_Device_Capabilities()
{
//Get the Capabilities structure for the device.
PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData (DeviceHandle, &PreparsedData);
HidP_GetCaps (PreparsedData, &Capabilities);
HidD_FreePreparsedData(PreparsedData);
}
/**
* Get_OutputReportByteLength
*
* Returns the output report length of the
* current device.
*
* @return Report Length.
*/
int Get_OutputReportByteLength ()
{
return Capabilities.OutputReportByteLength;
}
/**
* Write_Output_Report
*
* The function writes a byte array to the USB using WriteFile function. The
* api functions used are explained below.
*
* <B>WriteFile</B> Sends a report to the device. It returns success or failure.
* The function requires, a device handle returned by CreateFile, a buffer that
* holds the report, the Output Report length returned by HidP_GetCaps, a
* variable to hold the number of bytes written.
*
*/
void Write_Output_Report (char* data, int length)
{
//Send a report to the device.
DWORD BytesWritten = 0;
ULONG Result;
memcpy (OutputReport, data, length);
ResetEvent (hTxEventObj.hEvent);
if (DeviceHandle != INVALID_HANDLE_VALUE)
{
Result = WriteFile (DeviceHandle, OutputReport,
Capabilities.OutputReportByteLength,
&BytesWritten, &hTxEventObj);
while (!(HasOverlappedIoCompleted(&hTxEventObj)));
}
else
{
printf ("Invalid Write handle\n");
}
if (Result)
printf ("Can't write to device %ld, Bytes Written %ld\n", GetLastError(), BytesWritten);
else
GetLastError();
}
/**
* Close_Handles
*
* Close all the device handles.
*/
void Close_Handles()
{
//Close open handles.
//if (DeviceHandle == INVALID_HANDLE_VALUE)
//{
CloseHandle(DeviceHandle);
fprintf (stderr, "Device Handle closed \n");
//}
}
/**
* Read_Input_Report
*
* Function loops around till the handle is valid and tries to read packets from the USB. The
* main programs forks a seperate thread for this function to constantly monitory the
* incomming traffic.
*
* Few of the API calls used in this function are explained below.
*
* <B>ReadFile</B> returns the report in InputReport. It requires a device
* handle returned by CreateFile (for overlapped I/O, CreateFile must be called
* with FILE_FLAG_OVERLAPPED),the Input report length in bytes returned by
* HidP_GetCaps, and an overlapped structure whose hEvent member is set to
* an event object.
*
* <B>WaitForSingleObject</B> is used with overlapped ReadFile. It returns
* when ReadFile has received the requested data or on timeout. Requires
* an event object created with CreateEvent and a timeout value in milliseconds.
*
* <B>CancelIo</B> Cancels the ReadFile and returns non-zero on success.
*
* <B>ResetEvent</B> sets the event object to non-signaled. Requires a handle to
* the event object. Returns non-zero on success.
*
*/
void Read_Input_Report()
{
// Retrieve an Input report from the device.
short Result;
//OVERLAPPED overlapped;
while (DeviceHandle != INVALID_HANDLE_VALUE)
{
//The first byte is the report number.
InputReport[0]=0;
pthread_testcancel ();
if (DeviceHandle != INVALID_HANDLE_VALUE)
{
Result = ReadFile (DeviceHandle, InputReport,
Capabilities.InputReportByteLength, &NumberOfBytesRead,
(LPOVERLAPPED) &hRxEventObj);
}
//printf("The Last Error = %lx\n", GetLastError());
Result = WaitForSingleObject (hRxEventObj.hEvent, 1000);
pthread_testcancel ();
switch (Result)
{
case WAIT_OBJECT_0:
{
uint8_t type;
uint8_t valid;
USBdata *USBin;
USBdata USBData;
type = *(InputReport + IMOTE_HID_TYPE);
USBin = &USBData;
if(isFlagged(type, _BIT(IMOTE_HID_TYPE_H)))
{
USBin->i = 0;
USBin->type = type;
switch((USBin->type >> IMOTE_HID_TYPE_L) & 3)
{
case IMOTE_HID_TYPE_L_BYTE:
USBin->n = *(InputReport + IMOTE_HID_NI);
if (USBin->n == 0)
valid = *(InputReport + IMOTE_HID_NI + 1);
else
valid = IMOTE_HID_BYTE_MAXPACKETDATA;
USBin->data = (BYTE *)malloc(valid);
memcpy (USBin->data, InputReport + IMOTE_HID_NI + 1 +
(USBin->n == 0?1:0), valid);
break;
case IMOTE_HID_TYPE_L_SHORT:
USBin->n = (*(InputReport + IMOTE_HID_NI) << 8) |
*(InputReport + IMOTE_HID_NI + 1);
if(USBin->n == 0)
valid = *(InputReport + IMOTE_HID_NI + 2);
else
valid = IMOTE_HID_SHORT_MAXPACKETDATA;
USBin->data = (BYTE *)malloc(valid);
memcpy(USBin->data, InputReport + IMOTE_HID_NI + 2 +
(USBin->n == 0?1:0), valid);
break;
case IMOTE_HID_TYPE_L_INT:
USBin->n = (*(InputReport + IMOTE_HID_NI) << 24) |
(*(InputReport + IMOTE_HID_NI + 1) << 16) |
(*(InputReport + IMOTE_HID_NI + 2) << 8) |
*(InputReport + IMOTE_HID_NI + 3);
if(USBin->n == 0)
valid = *(InputReport + IMOTE_HID_NI + 4);
else
valid = IMOTE_HID_INT_MAXPACKETDATA;
USBin->data = (BYTE *)malloc(valid);
memcpy(USBin->data, InputReport + IMOTE_HID_NI + 4 +
(USBin->n == 0?1:0), valid);
break;
default:
//printf ("Not a valid case\n");
break;
}
if (((USBin->type >> 5) & 0x7) == IMOTE_HID_TYPE_MSC_BINARY)
{
Binary_Packet_Received (USBin->data, valid, USBin->n);
}
else if (((USBin->type >> 5) & 0x7) == IMOTE_HID_TYPE_MSC_COMMAND)
{
Command_Packet_Received (USBin->data);
}
else if (((USBin->type >> 5) & 0x7) == IMOTE_HID_TYPE_MSC_ERROR)
{
Error_Packet_Received (USBin->data);
}
else
{
fprintf (stderr, "Unknown USB Packet %d\n",USBin->type);
}
}
break;
}
case WAIT_TIMEOUT:
//printf ("ReadFile timeout.\n");
//Cancel the Read operation.
Result = CancelIo(DeviceHandle);
//A timeout may mean that the device has been removed.
//Close the device handles and set MyDeviceDetected = False
//so the next access attempt will search for the device.
//Close_Handles();
//printf ("Can't read from device\n");
//MyDeviceDetected = FALSE;
break;
default:
fprintf (stderr, "Undefined error\n");
//Close the device handles and set MyDeviceDetected = False
//so the next access attempt will search for the device.
Close_Handles();
fprintf (stderr, "Can't read from device \n");
MyDeviceDetected = FALSE;
break;
}
memset (InputReport, 0, 65);
ResetEvent(hRxEventObj.hEvent);
}
//Display the report data.
//DisplayInputReport();
}
--- NEW FILE: USBMessageHandler.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file USBMessageHandler.c
* @author Junaith Ahemed Shahabdeen
*
* This file provides a higher level USB Message
* parser and assembler. The message from the
* USB driver is identified by its message type
* and the required modules are invoked based on
* the type.
*/
#include <USBComm.h>
#include <USBMessageHandler.h>
#include <BinImageFile.h>
#include <BinImageUpload.h>
#include <BLAttrDefines.h>
#include <CommandLine.h>
#include <sys/time.h>
FILE *f = NULL;
uint16_t buffind = 0;
uint32_t fsize = 0;
double percent = 0;
struct timeval upstart, upend;
unsigned long uptelapsed = 0, upsec = 0, upusec = 0;
//#ifdef DEBUG
CmdReqBinData DbgRequest;
//#endif
/**
* Display_USB_Buffer
*
* This function dumps the data to the stdout.
*
* @param data Data to be dumped to stdout.
* @param len Size of data.
*/
void Display_USB_Buffer (uint8_t* data, uint8_t len)
{
int i = 0;
for (i = 0; i < len; i++)
{
printf ("%d ", data [i]);
}
printf ("\n");
}
/**
* Binary_Packet_Received
*
* Binary data received from the mote. Currently the mote sends
* a binary packet only when the pc requests a flash dump or a
* buffer dump.
*
* @param data Binary data from the mote.
* @param length Length of the data.
* @param seq Sequence number from the packet.
*/
result_t Binary_Packet_Received (char* data, uint8_t length, uint32_t seq)
{
//Display_USB_Buffer (data, 10);
if (f)
{
fwrite(data, length,1,f);
}
Get_Buffer_Dump ();
return SUCCESS;
}
/**
* Command_Packet_Received
*
* The function is signalled when a command packet is received
* from the device. The function parses the USB payload
* to determine the command type and calls the required module
* based on the type.
*
* @param data USB Payload.
*
* @return SUCCESS | FAIL
*/
result_t Command_Packet_Received (char* data)
{
USBCommand* cmd = (USBCommand*) data;
switch (cmd->type)
{
case CMD_BOOT_ANNOUNCE:
printf ("Recieved boot announce message \n");
break;
case CMD_GET_IMAGE_DETAILS:
{
gettimeofday (&upstart, NULL);
fprintf (stdout, "GET_IMAGE_DETAILS Received.\n");
//#if DEBUG
if (!Is_Test_Program_Mode ())
{
//#endif
USBCommand* cmdsend;
RspImageDetail* imgdetail;
uint32_t Length = sizeof(USBCommand) + sizeof(RspImageDetail);
fsize = Get_BinFile_Size();
cmdsend = (USBCommand*) malloc(Length);
if (cmdsend == NULL)
fprintf (stderr, "Error allocating memeory for command.\n");
cmdsend->type = RSP_GET_IMAGE_DETAILS;
imgdetail = (RspImageDetail*) cmdsend->data;
imgdetail->ImageSize = (uint32_t) Get_BinFile_Size ();
if (fsize % IMOTE_HID_SHORT_MAXPACKETDATA)
imgdetail->NumUSBPck = ((uint32_t) (fsize / IMOTE_HID_SHORT_MAXPACKETDATA)) + 1;
else
imgdetail->NumUSBPck = (uint32_t) (fsize / IMOTE_HID_SHORT_MAXPACKETDATA);
Send_USB_Command (cmdsend, Length);
free (cmdsend);
fprintf (stdout, "ImgSize=%ld, Num Packets= %ld\n", imgdetail->ImageSize, imgdetail->NumUSBPck);
//#if DEBUG
}
else
fprintf (stdout, "Waiting for user to send 'imagedetail' command\n");
//#endif
}
break;
case CMD_REQUEST_BIN_DATA:
{
//#if DEBUG
if (!Is_Test_Program_Mode ())
{
//#endif
uint32_t usize = 0;
float div = 0;
unsigned char percentsign [1] = "%";
CmdReqBinData* req = (CmdReqBinData*) cmd->data;
usize = (uint32_t) ((req->ChunkSize * IMOTE_HID_SHORT_MAXPACKETDATA) * 100);
div = (float) (usize / fsize);
printf ("Total Packets Uploaded = %ld, %.2lf%s completed \n", req->ChunkSize, div, percentsign);
Binary_Code_Upload (req->PckStart, req->NumUSBPck);
//#if DEBUG
}
else
{
memcpy (&DbgRequest, cmd->data, sizeof (CmdReqBinData));
fprintf (stdout, "Waiting for user to send 'sendbindata' command\n");
}
//#endif
}
break;
case CMD_REQUEST_BIN_PCK:
{
CmdReqBinData* req;
req = (CmdReqBinData*) cmd->data;
Send_Binary_Packet (req->PckStart, req->NumUSBPck, req->ChunkSize);
}
break;
case CMD_IMG_UPLOAD_COMPLETE:
fprintf (stdout, "Image Download Completed\n");
Send_Image_Crc_Command ();
gettimeofday (&upend, NULL);
upsec = (upend.tv_sec - upstart.tv_sec);
upusec = (upend.tv_usec - upstart.tv_usec);
uptelapsed = (upsec * 1000000) + upusec;
printf ("Time taken for Upload %ld Milli Seconds\n", (uptelapsed/1000));
break;
case CMD_IMG_VERIFY_COMPLETE:
if (Is_STImage ())
{
fprintf (stdout, "Image Verification Completed.\n");
fprintf (stdout, "Successfully Loaded Self Test Image.\n");
Exit_Application ();
}
else
{
fprintf (stdout, "Image Verification Completed.\n");
fprintf (stdout, "Loading Image to boot location and marking it as golden.\n");
Binary_Upload_Completed ();
gettimeofday (&upend, NULL);
upsec = (upend.tv_sec - upstart.tv_sec);
upusec = (upend.tv_usec - upstart.tv_usec);
uptelapsed = (upsec * 1000000) + upusec;
printf ("Time Elapsed till IMG_VERIFY %ld Milli Seconds\n", (uptelapsed/1000));
}
break;
case CMD_CREATED_GOLDEN_IMG:
{
uint8_t buff [61];
sprintf (buff, cmd->data, 61);
printf ("%s\n", buff);
gettimeofday (&upend, NULL);
upsec = (upend.tv_sec - upstart.tv_sec);
upusec = (upend.tv_usec - upstart.tv_usec);
uptelapsed = (upsec * 1000000) + upusec;
printf ("Overall Time Elapsed %ld Milli Seconds\n", (uptelapsed/1000));
Exit_Application ();
}
break;
case CMD_BOOTLOADER_MSG:
{
uint8_t buff [61];
gettimeofday (&upend, NULL);
upsec = (upend.tv_sec - upstart.tv_sec);
upusec = (upend.tv_usec - upstart.tv_usec);
uptelapsed = (upsec * 1000000) + upusec;
printf ("Time Elapsed %ld Milli Seconds\n", (uptelapsed/1000));
sprintf (buff, cmd->data, 61);
printf ("%s\n", buff);
}
break;
case CMD_RSP_GET_ATTRIBUTE:
{
uint32_t value;
Attribute* attr;
attr = (Attribute*)cmd->data;
memcpy (&value, attr->AttrValue, 4);
printf ("\nResponse for get attribute: \n");
//printf ("Attribute Type = %d \n", attr->AttrType);
//printf ("Attribute Validity = %d \n", attr->AttrValidity);
printf ("\tAttribute Length = %d \n", attr->AttrLength);
printf ("\tAttribute Value = %ld \n", value);
//Display_USB_Buffer (cmd->data, 62);
}
break;
case CMD_RSP_SET_ATTRIBUTE:
fprintf (stdout, "Set Attribute Successful\n");
break;
case CMD_TEST_IMG_DUMP:
fclose (f);
fprintf (stderr, "Image download Completed.\n");
break;
default:
printf ("**UNKNOWN** Command Received. Type = %d\n", cmd->type);
break;
}
return 0;
}
/**
* Error_Packet_Received
*
* This function is signalled when an error is received
* from the Device. The function parses the USB payload
* and takes appropriate measures based on the error.
*
* @param data Valid usb data.
* @return SUCCESS | FAIL
*/
result_t Error_Packet_Received (uint8_t* data)
{
USBError* err = (USBError*) data;
switch (err->type)
{
case ERR_FLASH_WRITE:
printf ("****** ERROR WRITING TO FLASH ****************\n");
break;
case ERR_FLASH_READ:
printf ("****** ERROR READING FROM FLASH ****************\n");
break;
case ERR_FLASH_ERASE:
{
uint32_t BlockAddress = 0;
mempcpy (&BlockAddress, err->description, 4);
printf ("****** ERROR ERASING FLASH BLOCK ****************\n");
printf ("Address = %ld\n", BlockAddress);
}
break;
case ERR_FATAL_ERROR_ABORT:
{
uint8_t buff [61];
printf ("**** FATAL ERROR ****. \nError from Device: ");
sprintf (buff, err->description, 61);
printf (" %s \n", buff);
//if (Is_STImage ())
Exit_Application ();
}
break;
case ERR_COMMAND_FAILED:
printf ("****** COMMAND FAILED ****************\n");
break;
case TEST_CRC_FAILURE:
{
CmdCrcData* chkcrc;
chkcrc = (CmdCrcData*) (err->description);
printf ("***** CRC ERROR Received ****** %ld,%ld,%d\n",
chkcrc->chunkStart, chkcrc->NumUSBPck,chkcrc->ChunkCRC);
}
break;
default:
printf ("**UNKNOWN** Command Received. Type = %d\n", err->type);
break;
}
return SUCCESS;
}
//#ifdef DEBUG
/**
* Dbg_Binary_Code_Upload
*
* Function used in the -tp option to send the
* image detail command to the device.
*
* @return SUCCESS | FAIL
*/
result_t Dbg_Binary_Code_Upload ()
{
Binary_Code_Upload (DbgRequest.PckStart, DbgRequest.NumUSBPck);
return SUCCESS;
}
//#endif
/**
* Get_Buffer_Dump
*
* The function requests the next packet from the IMote during
* flash dump mode. The process continues till the window size
* and is trigerred by the <I>Dump_From_Flash</I> function
* for the next buffer.
*
* @return SUCESS | FAIL
*/
result_t Get_Buffer_Dump ()
{
if (buffind < BIN_DATA_WINDOW_SIZE)
{
uint8_t buff [61];
USBCommand* cmd = (USBCommand*)buff;
USBImagePck* imgpck = (USBImagePck*) cmd->data;
cmd->type = RSP_TEST_GET_BUFFER_DATA;
imgpck->seq = buffind;
++ buffind;
Send_USB_Command (cmd, sizeof(USBCommand) + sizeof(USBImagePck));
}
else
{
printf ("Number of pck received = %d\n", buffind);
buffind = 0;
}
return SUCCESS;
}
/**
* Dump_From_Flash
*
* Request a data chunk from the flash, the length of the
* chunk and the flash address is passed as parameter to
* the function. This function basically triggers a request
* response cycle between the MOTE and the PC Application till
* the entire chunk is downloaded.
*
* @param addr Start address of the chunk in flash.
* @param length The size of the chunk.
*
* @return SUCCESS | FAIL
*/
result_t Dump_From_Flash (uint32_t addr, uint32_t length)
{
uint8_t buff [61];
USBCommand* cmd = (USBCommand*)buff;
cmd->type = RSP_DUMP_FLASH_DATA;
if (!f)
f=fopen("testdump.bin","a");
if (Send_USB_Command (cmd, (sizeof(USBCommand) + 1)) == SUCCESS)
{
++ buffind;
return SUCCESS;
}
return FAIL;
}
/**
* Send_USB_Command_Packet
*
* Send a command message to the Mote.
*
* @param cmd Command type defined in the enum (see MessageDefines.h).
* @param clen Length of the command data.
* @param cdata Command data in array format.
*
* @return SUCCESS | FAIL
*/
result_t Send_USB_Command_Packet (Commands cmd, uint8_t clen, void* cdata)
{
unsigned char OutputReport [Get_OutputReportByteLength()];
USBCommand* ucmd;
uint32_t length = sizeof (USBCommand) + clen;
OutputReport[0]=0;
/**
* Reboot need not be a seperate type, but inorder for the
* applicaiton to parse it easily, we are adding it as a
* seperate command.
*/
if (cmd == RSP_REBOOT)
{
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_COMMAND << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_BYTE << IMOTE_HID_TYPE_L);
}
else
{
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_COMMAND << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_BYTE << IMOTE_HID_TYPE_L);
}
OutputReport[IMOTE_HID_NI] = 0x01;
ucmd = (USBCommand*)(OutputReport + 3);
ucmd->type = cmd;
if (clen > 0)
memcpy (ucmd->data, cdata, clen);
Write_Output_Report (OutputReport, length + 3);
return SUCCESS;
}
/**
* Send_USB_Command
*
* Send a command message to the Mote.
*
* @param cmd Command struct with appropriate data defined in MessageDefines.h.
* @param length Length of the command data.
*
* @return SUCCESS | FAIL
*/
result_t Send_USB_Command (USBCommand* cmd, uint32_t length)
{
unsigned char OutputReport [Get_OutputReportByteLength()];
OutputReport[0]=0;
if (cmd->type == RSP_REBOOT)
{
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_REBOOT << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_BYTE << IMOTE_HID_TYPE_L);
}
else
{
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_COMMAND << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_BYTE << IMOTE_HID_TYPE_L);
}
OutputReport[IMOTE_HID_NI] = 0x01;
memcpy ((OutputReport + 3), cmd, length);
Write_Output_Report (OutputReport, length + 3);
return SUCCESS;
}
/**
* Send_Binary_Data
*
* Send a binary buffer to the device. Usually binary data is prepended
* with the sequence number of the packet the final packet will
* have a sequence number of 0. JT Protocol requires a header with the
* valid bytes in the packet if the seqence number is 0, this allows
* the pc host to send less than IMOTE_HID_TYPE_L_SHORT in the last
* packet if required.
*
* @param buff Pointer to the binary buffer.
* @param length Length of the buffer.
* @param seq Current Sequence number of the buffer.
*
* @return SUCCESS | FAIL
*/
result_t Send_Binary_Data (uint8_t* buff, uint32_t length, uint16_t seq)
{
unsigned char OutputReport [65];
OutputReport[0]=0;
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_BINARY << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_SHORT << IMOTE_HID_TYPE_L);
/**
* NOTE:
* Following Josh's protocol in which the last packet can
* specify the valid bytes
*/
if (length < IMOTE_HID_SHORT_MAXPACKETDATA)
{
OutputReport[IMOTE_HID_NI] = 0;
OutputReport[IMOTE_HID_NI + 1] = 0;
OutputReport[IMOTE_HID_NI + 2] = length; /* Specifies how many bytes are valid*/
memcpy (OutputReport + 5, buff, length);
Write_Output_Report (OutputReport, length + 5);
}
else
{
OutputReport[IMOTE_HID_NI] = ((seq >> 8) & 0xFF);
OutputReport[IMOTE_HID_NI + 1] = seq & 0xFF;
memcpy (OutputReport + 4, buff, length);
Write_Output_Report (OutputReport, length + 4);
}
return SUCCESS;
}
/**
* Send_USB_Binary_Data
*
* The function allows the user to send binary data packed in
* a structure.
*
* @param img The struct which contains binary data.
* @param length length of the struct with data.
*
* @return SUCCESS | FAIL
*/
result_t Send_USB_Binary_Data (USBImagePck* img, uint32_t length)
{
unsigned char OutputReport [Get_OutputReportByteLength()];
OutputReport[0]=0;
OutputReport[IMOTE_HID_TYPE] =
((IMOTE_HID_TYPE_MSC_BINARY << IMOTE_HID_TYPE_MSC) & 0xE3) |
_BIT(IMOTE_HID_TYPE_H) | (IMOTE_HID_TYPE_L_SHORT << IMOTE_HID_TYPE_L);
OutputReport[IMOTE_HID_NI] = 0x01;
memcpy ((OutputReport + 3), img, length);
Write_Output_Report (OutputReport, length + 3);
return SUCCESS;
}
--- NEW FILE: main.c ---
/* tab:4
* "Copyright (c) 2000-2003 The Regents of the University of California.
* All rights reserved.
*
* Permission to use, copy, modify, and distribute this software and its
* documentation for any purpose, without fee, and without written agreement is
* hereby granted, provided that the above copyright notice, the following
* two paragraphs and the author appear in all copies of this software.
*
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
*
* Copyright (c) 2002-2003 Intel Corporation
* All rights reserved.
*
* This file is distributed under the terms in the attached INTEL-LICENSE
* file. If you do not find these files, copies can be found by writing to
* Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA,
* 94704. Attention: Intel License Inquiry.
*/
/**
* @file main.c
* @author Junaith Ahemed Shahabdeen
*
* Entry point for the USB Loader application. The file provides
* an interface to the lower level windows drivers which is
* required to recieve notifications about changes at the lower level.
*
* The file actually creates and intializes a window with out displaying
* one. The reason is because the notification registration for the
* devices is possible only if the app is either a window based or a
* service based. It is a future requirement to enable window
* based applications hence a window based approach.
*/
#include <USBComm.h>
#include <USBMessageHandler.h>
#include <CommandLine.h>
#include <BinImageFile.h>
#include <sys/time.h>
#include <sys/signal.h>
#define MAX_FILE_NAME_SIZE 1024
pthread_t thread_rx, thread_cmd;
struct sigaction actions;
BOOLEAN ProgramMode = FALSE;
BOOLEAN STImage = FALSE;
BOOLEAN TestProgramMode = FALSE;
BOOLEAN CmdLineMode = FALSE;
BOOLEAN DownloadDone = FALSE;
char FileName [MAX_FILE_NAME_SIZE] = "\0";
HWND hwnd;
MSG Msg;
HDEVNOTIFY DeviceNotificationHandle;
struct timeval start, end;
unsigned long timeelapsed = 0, sec = 0, usec = 0;
struct timeval now; /* time when we started waiting */
struct timespec timeout; /* timeout value for the wait function */
int done; /* are we done waiting? */
pthread_cond_t got_request = PTHREAD_COND_INITIALIZER;
pthread_mutex_t req_mutex = PTHREAD_MUTEX_INITIALIZER;
const char g_szClassName[] = "myWindowClass";
/**
* print_help
*
* This function prints the help menu for the main app.
*/
void print_help ()
{
printf ("out.exe [Options] [FileName]\n");
printf ("Options:\n");
printf (" -p FileName:\t Upload a binary file to the Device.\n");
printf (" -tp FileName:\t Upload a binary file to the Device in\n");
printf ("\t\t a interactively. The display guides the user about\n");
printf ("\t\t the next action required. If the user has to send\n");
printf ("\t\t a command with parameter, then the value of the\n");
printf ("\t\t parameters are diplayed in stdout.\n");
printf (" -c\t\t Place the Device in command line mode.\n");
printf (" -pst\t\t FileName: Upload selftest image to the device.\n");
}
/**
* Register_For_Device_Notifications
*
* Register a particular Class of device with the lover level
* driver interface to get notifications about any changes in
* the device status (attached, detached etc.)
*
* @param HidGuid GUID of a particular class.
*/
void Register_For_Device_Notifications(GUID HidGuid)
{
// Request to receive messages when a device is attached or removed.
// Also see WM_DEVICECHANGE in BEGIN_MESSAGE_MAP(CUsbhidiocDlg, CDialog).
DEV_BROADCAST_DEVICEINTERFACE DevBroadcastDeviceInterface;
ZeroMemory (&DevBroadcastDeviceInterface, sizeof(DevBroadcastDeviceInterface));
DevBroadcastDeviceInterface.dbcc_size = sizeof(DevBroadcastDeviceInterface);
DevBroadcastDeviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
DevBroadcastDeviceInterface.dbcc_classguid = HidGuid;
DeviceNotificationHandle = RegisterDeviceNotification (hwnd,
&DevBroadcastDeviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
if (!DeviceNotificationHandle)
{
printf ("Registration Failed = %lx\n", GetLastError());
}
}
/**
* WndProc
*
* Call back funciton registerd with the lower level driver which gets
* invoked when there are any changes with the device attached or
* events related to this process.
*
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
//printf ("Window Created \n");
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEARRIVAL:
if (DownloadDone)
{
fprintf (stderr, "Booted New Application.\n");
Exit_Application ();
}
if (DeviceNotificationHandle)
UnregisterDeviceNotification (DeviceNotificationHandle);
USB_Init ();
//#if DEBUG
if (!TestProgramMode)
{
//#endif
if (ProgramMode)
{
uint8_t imgtyp = APPLICATION;
if (STImage)
imgtyp = SELFTEST;
if (Send_USB_Command_Packet (RSP_USB_CODE_LOAD, 1, &imgtyp) == FAIL)
fprintf (stderr, "Could not place the Device in upload mode\n");
}
//#if DEBUG
}
else
fprintf (stdout, "Start upload by sending the loadcode command\n");
//#endif
// I dont have a very good way to set the correct BL State.
if ((CmdLineMode) || (Is_Test_Program_Mode()))
{
uint8_t BLState = 8;
Send_USB_Command_Packet (RSP_SET_BOOTLOADER_STATE, 1, &BLState);
}
break;
case DBT_DEVICEREMOVECOMPLETE:
break;
default:
break;
}
break;
default:
//printf ("Unkown event \n");
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
/**
* WinMain
*
* Window Main function, The low level events from windows are
* directly passed to a program if it is a service or a window
* based application. Since at some point a window application
* is required to be an extension of this applicaiton, it is
* easier to create a window than a service based application.
*/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
bool detectUSB = TRUE;
uint8_t NumTries = 0;
//Step 1: Registering the Window Class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
printf ("Window Registration Failed! %lx \n", GetLastError ());
return 0;
}
hwnd = CreateWindowEx (WS_EX_CLIENTEDGE, g_szClassName,
"Code Loader", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL);
if(hwnd == NULL)
{
printf ("Window Creation Failed! %lx \n", GetLastError ());
return 0;
}
//ShowWindow(hwnd, nCmdShow);
//UpdateWindow(hwnd);
if (lpCmdLine [0] != '\0')
Parse_Arguments (lpCmdLine);
else
{
print_help ();
exit (1);
}
if (ProgramMode)
{
if (strcmp(FileName, "\0") != 0)
{
fprintf (stdout, "Program Mode, File name = %s\n", FileName);
if (Load_Binary_File (FileName) == FAIL)
{
ProgramMode = FALSE;
fprintf (stderr, "Problem loading Binary file, exiting program mode \n");
exit (1);
}
}
else
{
ProgramMode = FALSE;
fprintf (stderr, "Cannot enter Program Mode, no File specified \n");
exit (1);
}
}
while (detectUSB)
{
if (USB_Init () == SUCCESS)
{
detectUSB = FALSE;
pthread_create (&thread_rx, NULL, (void*)Read_Input_Report, NULL);
//#if DEBUG
//if (!Is_Test_Program_Mode ())
//{
//#endif
if (ProgramMode)
{
USBCommand cmdsend;
cmdsend.type = RSP_REBOOT;
Send_USB_Command (&cmdsend, sizeof (USBCommand));
}
//#if DEBUG
//}
//#endif
if ((CmdLineMode) || (Is_Test_Program_Mode()))
{
uint8_t BLState = 8;
Send_USB_Command_Packet (RSP_SET_BOOTLOADER_STATE, 1, &BLState);
pthread_create (&thread_cmd, NULL, (void*)Command_Line, NULL);
}
}
else
{
printf ("Device not connected to USB. Retry\n");
if ((++ NumTries) < 3)
Sleep (2000);
else
{
detectUSB = FALSE;
printf ("USB Communication Failed. Device not connected to USB.\n");
exit (0);
}
}
}
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
/**
* Parse_Arguments
*
* Parse the arguments from the command line of the
* terminal. The function passed each argument to CmdLine_Argument
* function which will perform necessary action based
* on the argument.
*
* @param argv The argument list passed through the command line
*/
void Parse_Arguments (LPSTR argv)
{
if (argv [0] != '\0')
{
LPSTR p = argv;
char* s = strtok (p, " ");
CmdLine_Argument (s);
while ((s = strtok (NULL, " ")) != '\0')
{
CmdLine_Argument (s);
}
}
}
/**
* CmdLine_Argument
*
* This function identifies each argument from the argument list
* passed through the command line and performs specific actions
* based on the argument.
*
* @param par Parsed argument from Parse_Argument function.
*/
void CmdLine_Argument (char* par)
{
if (strcmp (par, "-p") == 0)
ProgramMode = TRUE;
else if (strcmp (par, "-c") == 0)
CmdLineMode = TRUE;
else if (strcmp (par, "-pst") == 0)
{
ProgramMode = TRUE;
STImage = TRUE;
}
else if (strcmp (par, "-help") == 0)
{
print_help ();
exit (0);
}
//#ifdef DEBUG
else if (strcmp (par, "-tp") == 0)
{
TestProgramMode = TRUE;
ProgramMode = TRUE;
}
//#endif
else if (par[0] != '-')
{
strncpy (FileName, par, MAX_FILE_NAME_SIZE);
}
else
{
fprintf (stderr, "Ignoring unknown argument %s.", par);
}
}
/**
* Is_STImage
*
* Check if we are downloading SELF Test Image to the
* device. The function returns boolean variable
* STImage.
*
* @return STImage TRUE | FALSE
*/
BOOLEAN Is_STImage ()
{
return STImage;
}
/**
* Is_Test_Program_Mode
*
* Returns the boolean variable TestProgramMode. If the application is
* compiled with DEBUG flag then it accepts an extra command
* line parameter '-tp' which provides step by step control to the user
* over the communication with the bootloader.
*
* @return TestProgramMode = TRUE | FALSE
*/
BOOLEAN Is_Test_Program_Mode ()
{
return TestProgramMode;
}
/**
* Binary_Upload_Completed
*
* Reverts the programming mode. Checks if the application has to
* stay in command line mode.
*/
void Binary_Upload_Completed ()
{
ProgramMode = FALSE;
DownloadDone = TRUE;
//TestProgramMode = FALSE;
}
/**
* Exit_Applicaiton
*
* This function provides a reliable way of exiting the application.
* It makes sure that the threads are terminated before the exit
* function is call. It is advisable to call this function for a
* clean exit rather than using exit(0).
*/
void Exit_Application ()
{
//pthread_kill (thread_rx, 0);
//pthread_kill (thread_cmd, 0);
pthread_cancel (thread_rx);
pthread_cancel (thread_cmd);
exit (0);
}
More information about the Tinyos-contrib-commits
mailing list