class project main.cpp publish
Dependencies: mbed C12832_lcd USBHost USBHostPTP LCD_Menu
mbed PTP hosting library
USB Device Interface: Architecture, Protocols, and Programming Class Project
Goal
Provide a generic PTP library to allow the mBed to host a PTP device
Details
- Main thread configures and displays the Menu system, as Commands are selected in the menu a command value is set.
- MSD thread blocks until a MSd device is connected, If a device is removed it will try to reconnect
- PTP thread blocks until a PTP device ois connected. After connection of device, a session is opened, device information is retriewved, and object handles are recieved. As long as a PTP device is connected, the command value is checked for a non-zero value. when a command code is recieved, the statusFunction is changed from NULL, and the command executed. After execution the command code is cleared.
Project Hardware
- mbed LPC1768 CPU board
- mbed DEV-11695 application board
- USB HUB
- USB Mass Storage Device
- Camera using PTP Protocol
- Three USB Cables (normal mbed connection, connection to USB HUB, and connection to camera)
Testing
Test Item | Description | Status | ||||||
Unit Tests | ||||||||
connected1 | Test connected with a device. | Pass | ||||||
connected2 | Test connected without a device. | Pass | ||||||
connect1 | Test Connect() with no device | Pass | ||||||
connect2 | Test connect() with a ptp device | Pass | ||||||
connect3 | Test connect() with multiple PTP devices | Not Tested | ||||||
connect4 | Test Connect() with multiple PTP devices and, Classes | Not Tested | ||||||
cancel1 | Test CancelRequest() with invalid transactionID | Not Tested | ||||||
cancel2 | Test CancelRequest() with valid transactionID | Not Tested | ||||||
reset1 | Test DeviceReestRequest on Device that supports the call | Not Tested | ||||||
reset2 | Test DeviceReestRequest on Device that does not supports the call | Not Tested | ||||||
status1 | Test GetDeviceStatus returns status | Not Tested | ||||||
extended1 | Test if GetExtendedEventData functions on device that does not support it. | Not Tested | ||||||
transaction1 | Test transaction() with unsupported opcode | Pass | ||||||
transaction2 | Test transaction() with supported opcode | Pass | ||||||
transaction3 | Test transaction() with opcode other than OpenSession or GetDeviceInfo before a session is openned. | Pass | ||||||
transaction4 | Test transaction() with getDeviceInfo before OpenSession | Pass | ||||||
transaction5 | Test transaction() with max number parameter | Pass | ||||||
transaction6 | Test transaction() with no parameters | Pass | ||||||
transaction7 | Test transaction() with 1 parameter | Pass | ||||||
transaction8 | Test transaction() with no data stage | Pass | ||||||
transaction9 | Test transaction() with 1 input data stage | Pass | ||||||
transaction10 | Test transaction() with data stage that spans max packet size | Pass | ||||||
transaction11 | Test transaction() with Response container that has no paramerters | Pass | ||||||
transaction12 | Test transaction() with response container that has parameters | Pass | ||||||
operation1 | Test Operation() call without params | Not Tested | ||||||
operation2 | Test Operation() call with parameters | Not Tested | ||||||
opensession1 | Test OpenSession opens a session | Pass | ||||||
close1 | Test Close Session closes a session | Pass | ||||||
close2 | Test Close Session with an invlid sesison number | Not Tested | ||||||
deviceinfo1 | Test getDeviceInfo obtains a device Info structure | Pass | ||||||
powerdown1 | Test powerdown() on a device that does not support powerdown. | Not Tested | ||||||
selftest1 | Test SelfTest on device that does not support selftest. | Not Tested | ||||||
getobjecthandkles1 | GetObject handles for an empty device | Pass | ||||||
getobjecthandles2 | GetObjectHandles for all types. | Pass | ||||||
getobjecthandles3 | Get ObjectHandles filtered by type | Not Tested | ||||||
getobjecthandles4 | GetObjectHandles filtered by association | Not Tested | ||||||
getnumobjects1 | Test GetNumObjects for all types | |||||||
getnumobjects2 | Test GetNumObjects for only image types | |||||||
getnumobjects3 | Test GetNumObjects filtered by assoication | Not Tested | ||||||
getobject1 | Test getObjectInfo for image types | |||||||
getobject2 | Test getObjectInfo for non-image type | |||||||
getthumb1 | Test getThumb for an object that has no Thumb | |||||||
getthumb2 | Test getThumb for an image object | |||||||
getstorageids1 | Test getStorageIDs gets the handles for the storage devices. | |||||||
copyobject1 | Test CopyObject can copy an Object to a new location | Not Tested | ||||||
copyobject2 | Test CopyObject fails for invalid handle | Not Tested | ||||||
copyobject3 | Test CopyObject fails for invalid storageID | Not Tested | ||||||
copyobject4 | Test CopyObject fails for invalid parent | Not Tested | ||||||
copyobject5 | Test CopyObject returns a new handle in the varaible provided | Not Tested | ||||||
deleteobject1 | Test DeleteObject can remove an object | Not Tested | ||||||
deleteobject2 | Test DeleteObject fails for invalid handle | Not Tested | ||||||
deleteobject3 | Test DeleteObject with the Format field | Not Tested | ||||||
protect1 | Test SetObjectProtection on a device that does not support the action. | Not Tested | ||||||
prop1 | Test GetDevicePropertyDesc functions | Not Tested | ||||||
prop2 | Test GetDeviceProperty functions | Not Tested | ||||||
prop3 | Test SetDeviceProperty Functions | Not Tested | ||||||
prop4 | Test ResetDeviceProperty funxctions | Not Tested | ||||||
Functional | ||||||||
flow1 | "Complete flow-poweron, connect msd, connect PTP, all thumbs and files transferred" | Pass | ||||||
Stress | ||||||||
stress1 | Contious transfer of same image | Pass | ||||||
stress2 | Transfer of all images on camera - Continous. | Fail | Buffer Overflow. | |||||
Performance | ||||||||
perf1 | Image transfer time per image | |||||||
perf2 | Thumb transfer time per image | |||||||
Interoperability | ||||||||
compat1 | Motorola Droid4 in Camera mode | Pass | ||||||
compat2 | Cannon Eos 10D | Fail | ||||||
compat3 | Cannon Powershot a1400 | Pass | ||||||
power up/ power down | ||||||||
power1 | No devices present | Pass | ||||||
power2 | MSD only present | Pass | ||||||
power3 | PTP Only present | Pass | ||||||
power4 | Both devices present | Pass | ||||||
USB Compliance | ||||||||
Compliance1 | Beagle USB trace tool able to track packets and class data. | Fail | USBHost not compliant. | |||||
Compliance2 | "Verify Control, Bulk_in, bulk_out and Interupt_in endpoints function." | Pass |
Example of using the USBHostPTP class
Import program
00001 /** 00002 * @file main.cpp 00003 * @brief Function to call USBHostPTP Library 00004 * @author Dwayne Dilbeck 00005 * @date 8/23/2013 00006 * 00007 * mbed USBHostPTP Library 00008 * 00009 * @par Copyright: 00010 * Copyright (c) 2013 Dwayne Dilbeck 00011 * @par License: 00012 * This software is distributed under the terms of the GNU Lesser General Public License 00013 */ 00014 #include "mbed.h" 00015 #include "C12832_lcd.h" 00016 #include "USBHostMSD.h" 00017 #include "USBHostPTP.h" 00018 #include "Selection.h" 00019 #include "Menu.h" 00020 #include "Navigator.h" 00021 00022 /** 00023 * Define codes to represent Test Functions 00024 */ 00025 #define GETALLJPG 0x01 00026 #define GETALLJPGTHUMB 0x02 00027 #define GETNUMJPG 0x03 00028 #define GETNUMOBJ 0x04 00029 #define DUMPDEVICEINFO 0x05 00030 #define CLOSESESSION 0xFF 00031 00032 /** 00033 * Initiate Global variables 00034 */ 00035 DigitalOut led(LED1); 00036 FILE * fp2; 00037 C12832_LCD lcd; 00038 USBHostPTP *ptpdev = NULL; 00039 USBHostMSD *msddev = NULL; 00040 char fname[256]; 00041 uint8_t command=0x00; 00042 bool commandActive=false; 00043 void (*statusFunction)(void); 00044 00045 /** 00046 * This function is used to handle the raw data recieved via the bulk pipes 00047 * 00048 * @param ptp Pointer to the PTP device 00049 * @param buffer Pointer to the data recieved 00050 * @param length Total data received to be processed 00051 * 00052 * @return Void 00053 */ 00054 void WriteObjectHandles(void *ptp,uint8_t *buffer,uint16_t length){ 00055 int writeResult,errorcode; 00056 uint16_t transferLength=length; 00057 uint8_t *dataPtr=buffer; 00058 00059 writeResult=fwrite(dataPtr,sizeof(uint8_t),transferLength,fp2); 00060 if( writeResult != transferLength) { 00061 errorcode=ferror(fp2); 00062 if( errorcode ) 00063 { 00064 printf("\r\nError in writing to file %d\n",errorcode); 00065 error("Yucky@!"); 00066 } 00067 } 00068 } 00069 00070 /** 00071 * Test function 0x01 00072 * 00073 * @param numberOfImages A pointer to where to write the images on the device 00074 * @param numberOfThumbs A pointer to where to write the images on the device 00075 * @return void 00076 */ 00077 void GetNumberOfThumbsAndImages(int *numberOfImages,int *numberOfThumbs){ 00078 uint32_t fileHandle=0,numImages=0; 00079 int internalNumberOfImages=0; 00080 int internalNumberOfThumbs=0; 00081 00082 FILE *fp = fopen("/usb2/objHandles.bin", "rb"); 00083 fread(&numImages,sizeof(uint32_t),1,fp); 00084 while(numImages>0){ 00085 fread(&fileHandle,sizeof(uint32_t),1,fp); 00086 ptpdev->GetObjectInfo(fileHandle); 00087 00088 if (ptpdev->objectInfo.thumbFormat == 0x3801 ) { 00089 internalNumberOfThumbs++; 00090 } 00091 if (ptpdev->objectInfo.objectFormat == 0x3801 ) { 00092 internalNumberOfImages++; 00093 } 00094 numImages--; 00095 } 00096 fclose(fp); 00097 *numberOfImages = internalNumberOfImages; 00098 *numberOfThumbs = internalNumberOfThumbs; 00099 00100 } 00101 00102 /** 00103 * Retrieve all thumbnail images and real images that are JPG files. 00104 */ 00105 void GetAllImagesAndThumbs(void) { 00106 FILE *fp; 00107 00108 uint32_t fileHandle=0,numImages=0; 00109 00110 printf("objectid,objectinfosize,imagetype,thumbtype\r\n"); 00111 fp = fopen("/usb2/objHandles.bin", "rb"); 00112 00113 fread(&numImages,sizeof(uint32_t),1,fp); 00114 while(numImages>0){ 00115 fread(&fileHandle,sizeof(uint32_t),1,fp); 00116 ptpdev->GetObjectInfo(fileHandle); 00117 printf("%ld,%x,%x,%x\r\n",numImages,fileHandle,ptpdev->objectInfo.objectFormat,ptpdev->objectInfo.thumbFormat); 00118 00119 if (ptpdev->objectInfo.thumbFormat == 0x3801 && numImages < 864 ) { 00120 sprintf(fname,"/usb2/thumb_%s",ptpdev->objectInfo.filename.getString()); 00121 fp2 = fopen(fname, "wb"); 00122 printf("Starting transfer of %s\r\n",fname); 00123 ptpdev->GetThumb(fileHandle,(void *)&WriteObjectHandles); 00124 fclose(fp2); 00125 printf("GetThumb Transaction Complete\r\n"); 00126 } 00127 00128 if (ptpdev->objectInfo.objectFormat == 0x3801 && numImages < 864 ) { 00129 sprintf(fname,"/usb2/%s",ptpdev->objectInfo.filename.getString()); 00130 printf("%s -Type: 0x%04x\r\n",fname,ptpdev->objectInfo.objectFormat); 00131 printf("Starting transfer of %s\r\n",fname); 00132 fp2 = fopen(fname, "wb"); 00133 ptpdev->GetObject(fileHandle,(void *)&WriteObjectHandles); 00134 fclose(fp2); 00135 printf("GetObject Transaction Complete\r\n"); 00136 } 00137 numImages--; 00138 } 00139 fclose(fp); 00140 } 00141 00142 /** 00143 * Thread to Watch for MSD image 00144 */ 00145 void msd_task(void const *) { 00146 USBHostMSD msd2("usb2"); 00147 00148 msddev=&msd2; 00149 while(true) { 00150 while(!msd2.connect()) { 00151 Thread::wait(500); 00152 } 00153 00154 DIR *dp; 00155 struct dirent *ep; 00156 dp = opendir ("/usb2"); 00157 00158 if (dp != NULL) 00159 { 00160 ep = readdir (dp); 00161 while (ep!=NULL) { 00162 printf("%s\r\n",ep->d_name); 00163 ep = readdir (dp); 00164 } 00165 (void) closedir (dp); 00166 } 00167 00168 while(msd2.connect()) { 00169 Thread::wait(500); 00170 } 00171 } 00172 } 00173 00174 /** 00175 * Function TO be called by the menu system to start the execution thread to execute the call. 00176 */ 00177 void SetCommandGETALLJPG(void) { 00178 command=GETALLJPG; 00179 } 00180 00181 /** 00182 * Function to display status during image transfers 00183 */ 00184 void GetAllJPGStatus(void) { 00185 led=!led; 00186 lcd.cls(); 00187 if(ptpdev->dataLeftToTransfer>0) { 00188 lcd.locate(10,0); 00189 lcd.printf("%ld/%ld", ptpdev->dataLeftToTransfer, ptpdev->totalDataToTransfer); 00190 lcd.locate(0,10); 00191 lcd.printf("%s",fname); 00192 } 00193 } 00194 00195 /** 00196 * Thread to watch for the PTP device connected, and commands that need to be executed. 00197 */ 00198 void ptp_task2(void const *) { 00199 USBHostPTP ptp; 00200 ptpdev=&ptp; 00201 00202 int numi,numt; 00203 uint32_t objCount=0; 00204 00205 while(true) { 00206 while(!ptpdev->connect()) { 00207 Thread::wait(500); 00208 } 00209 00210 while(!msddev->connected()){ 00211 Thread::wait(500); 00212 } 00213 00214 /* after device connected open a session, get device information, and object handles 00215 */ 00216 ptp.OpenSession(); 00217 printf("OpenSession Transaction Complete\r\n\r\n"); 00218 ptp.GetDeviceInfo(); 00219 printf("GetDeviceInfo Transaction Complete\r\n"); 00220 fp2 = fopen("/usb2/objHandles.bin", "wb"); 00221 ptp.GetObjectHandles(0xffffffff,0x0000,0x0000,(void *)&WriteObjectHandles); 00222 fclose(fp2); 00223 printf("GetObjecthandles Transaction Complete\r\n"); 00224 00225 //While ptp device connected watch for commands. 00226 while(ptpdev->connected()) { 00227 commandActive=true; 00228 switch(command) { 00229 case GETALLJPG: 00230 statusFunction=&GetAllJPGStatus; 00231 GetAllImagesAndThumbs(); 00232 statusFunction=NULL; 00233 break; 00234 case GETALLJPGTHUMB: 00235 break; 00236 case GETNUMJPG: 00237 GetNumberOfThumbsAndImages(&numi,&numt); 00238 printf("images: %d, thumbs:%d\r\n",numi,numt); 00239 break; 00240 case GETNUMOBJ: 00241 ptp.GetNumObjects(&objCount); 00242 printf("GetNumObjects Transaction Complete - Count:%ld\r\n",objCount); 00243 break; 00244 case DUMPDEVICEINFO: 00245 ptp.DumpDeviceInfo(); 00246 break; 00247 case CLOSESESSION: 00248 ptpdev->CloseSession(); 00249 printf("CloseSession Transaction Complete\r\n"); 00250 break; 00251 default: 00252 commandActive=false; 00253 break; 00254 } 00255 command=0x00; 00256 Thread::wait(100); 00257 } 00258 } 00259 } 00260 00261 ///Menu function to set the Command to be executed. 00262 void SetCommandGETNUMJPG(void) { 00263 command=GETNUMJPG; 00264 } 00265 00266 ///Menu function to set the Command to be executed. 00267 void SetCommandGETNUMOBJ(void) { 00268 command=GETNUMOBJ; 00269 } 00270 00271 ///Menu function to set the Command to be executed. 00272 void SetCommandDUMPDEVICEINFO(void) { 00273 command=DUMPDEVICEINFO; 00274 } 00275 00276 ///Menu function to set the Command to be executed. 00277 void SetCommandCLOSESESSION(void) { 00278 command=CLOSESESSION; 00279 } 00280 00281 ///Main fuction to display the Status of the application. 00282 int main() { 00283 lcd.cls(); 00284 lcd.locate(10,3); 00285 lcd.printf("Initializing"); 00286 Thread ptpTask2(ptp_task2, NULL, osPriorityNormal, 1024 * 4); 00287 Thread msdTask2(msd_task, NULL, osPriorityNormal, 1024 * 4); 00288 Menu rootMenu("root"); 00289 Menu testMenu("Test menu"); 00290 testMenu.add(Selection(&SetCommandDUMPDEVICEINFO, 2, NULL, "Dump Device Info")); // The function argument of selection can be added directly 00291 testMenu.add(Selection(&SetCommandGETALLJPG, 2, NULL, "Get All Images")); // The function argument of selection can be added directly 00292 testMenu.add(Selection(&SetCommandGETNUMOBJ, 1, NULL, "Get Number of Objects")); 00293 testMenu.add(Selection(&SetCommandGETNUMJPG, 3, NULL, "Get Number of Images")); 00294 //testMenu.add(Selection(NULL, 4, NULL, "Get Number of Thumbnails")); 00295 //testMenu.add(Selection(NULL, 5, NULL, "Get Number of Thumbnails")); 00296 testMenu.add(Selection(&SetCommandCLOSESESSION, 4, NULL, "Close Session")); 00297 testMenu.add(Selection(NULL, 5, &rootMenu, " Go back")); // always add a Selection at the end to point to the parent 00298 Menu aboutMenu("About Menu"); // about menu 00299 aboutMenu.add(Selection(NULL, 0, NULL, "Author:")); 00300 aboutMenu.add(Selection(NULL, 1, NULL, " Dwayne S Dilbeck")); 00301 aboutMenu.add(Selection(NULL, 2, NULL, " 8/29/2013")); 00302 aboutMenu.add(Selection(NULL, 3, NULL, " USB Device Interface:")); 00303 aboutMenu.add(Selection(NULL, 4, NULL, " Architecture,")); 00304 aboutMenu.add(Selection(NULL, 5, NULL, " Protocols,")); 00305 aboutMenu.add(Selection(NULL, 6, NULL, " and programming.")); 00306 aboutMenu.add(Selection(NULL, 7, &rootMenu, " Go back")); 00307 rootMenu.add(Selection(NULL, 0, &testMenu, "TEST MENU")); 00308 rootMenu.add(Selection(NULL, 1, &aboutMenu, "About menu")); 00309 Navigator navigator(&rootMenu, &lcd); 00310 00311 while(1) { 00312 if(ptpdev != NULL) { 00313 if(ptpdev->connected()) { 00314 if(!commandActive) { 00315 navigator.poll(); 00316 } else { 00317 if(statusFunction != NULL) 00318 (*statusFunction)(); 00319 else { 00320 lcd.cls(); 00321 wait_ms(20); 00322 } 00323 } 00324 00325 } else { 00326 lcd.cls(); 00327 lcd.locate(10,3); 00328 lcd.printf("Please connect PTP device."); 00329 } 00330 } 00331 Thread::wait(200); 00332 } 00333 } 00334 00335 00336 00337
Known Issues
- Buffer overflow will halt the mbed device after 6 hours of transfers
- Method Transaction is unable to SEND Data Containers
- MSD removal does not change the Data container handler. This should become NULL, when the MSD is removed.
Future Work
- Find the buffer overflow
- Implement a PTP Capture Test.
- Implement send data in method Transaction
- Implement an Opcode decoder
- Add Canon extended PTP support.
References
- PIMA15740
- PTP Vedor code list
- Arduino Camera Capture Library
main.cpp@5:013bdb272a9c, 2013-09-03 (annotated)
- Committer:
- jakowisp
- Date:
- Tue Sep 03 10:30:07 2013 +0000
- Revision:
- 5:013bdb272a9c
- Parent:
- 4:a95225ec39ac
- Child:
- 6:2e2cb26d4079
Change the LCD refresh
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jakowisp | 4:a95225ec39ac | 1 | /** |
jakowisp | 4:a95225ec39ac | 2 | * @file main.cpp |
jakowisp | 4:a95225ec39ac | 3 | * @brief Function to call USBHostPTP Library |
jakowisp | 4:a95225ec39ac | 4 | * @author Dwayne Dilbeck |
jakowisp | 4:a95225ec39ac | 5 | * @date 8/23/2013 |
jakowisp | 4:a95225ec39ac | 6 | * |
jakowisp | 4:a95225ec39ac | 7 | * mbed USBHostPTP Library |
jakowisp | 4:a95225ec39ac | 8 | * |
jakowisp | 4:a95225ec39ac | 9 | * @par Copyright: |
jakowisp | 4:a95225ec39ac | 10 | * Copyright (c) 2013 Dwayne Dilbeck |
jakowisp | 4:a95225ec39ac | 11 | * @par License: |
jakowisp | 4:a95225ec39ac | 12 | * This software is distributed under the terms of the GNU Lesser General Public License |
jakowisp | 4:a95225ec39ac | 13 | */ |
jakowisp | 0:ec1356628850 | 14 | #include "mbed.h" |
jakowisp | 0:ec1356628850 | 15 | #include "C12832_lcd.h" |
jakowisp | 0:ec1356628850 | 16 | #include "USBHostMSD.h" |
jakowisp | 0:ec1356628850 | 17 | #include "USBHostPTP.h" |
jakowisp | 3:1e2f56de7d5d | 18 | #include "Selection.h" |
jakowisp | 3:1e2f56de7d5d | 19 | #include "Menu.h" |
jakowisp | 3:1e2f56de7d5d | 20 | #include "Navigator.h" |
jakowisp | 3:1e2f56de7d5d | 21 | |
jakowisp | 4:a95225ec39ac | 22 | /** |
jakowisp | 4:a95225ec39ac | 23 | * Define codes to represent Test Functions |
jakowisp | 4:a95225ec39ac | 24 | */ |
jakowisp | 3:1e2f56de7d5d | 25 | #define GETALLJPG 0x01 |
jakowisp | 3:1e2f56de7d5d | 26 | #define GETALLJPGTHUMB 0x02 |
jakowisp | 3:1e2f56de7d5d | 27 | #define GETNUMJPG 0x03 |
jakowisp | 3:1e2f56de7d5d | 28 | #define GETNUMOBJ 0x04 |
jakowisp | 3:1e2f56de7d5d | 29 | #define DUMPDEVICEINFO 0x05 |
jakowisp | 3:1e2f56de7d5d | 30 | #define CLOSESESSION 0xFF |
jakowisp | 3:1e2f56de7d5d | 31 | |
jakowisp | 4:a95225ec39ac | 32 | /** |
jakowisp | 4:a95225ec39ac | 33 | * Initiate Global variables |
jakowisp | 4:a95225ec39ac | 34 | */ |
jakowisp | 0:ec1356628850 | 35 | DigitalOut led(LED1); |
jakowisp | 0:ec1356628850 | 36 | FILE * fp2; |
jakowisp | 0:ec1356628850 | 37 | C12832_LCD lcd; |
jakowisp | 3:1e2f56de7d5d | 38 | USBHostPTP *ptpdev = NULL; |
jakowisp | 3:1e2f56de7d5d | 39 | USBHostMSD *msddev = NULL; |
jakowisp | 0:ec1356628850 | 40 | char fname[256]; |
jakowisp | 3:1e2f56de7d5d | 41 | uint8_t command=0x00; |
jakowisp | 3:1e2f56de7d5d | 42 | bool commandActive=false; |
jakowisp | 3:1e2f56de7d5d | 43 | void (*statusFunction)(void); |
jakowisp | 0:ec1356628850 | 44 | |
jakowisp | 4:a95225ec39ac | 45 | /** |
jakowisp | 4:a95225ec39ac | 46 | * This function is used to handle the raw data recieved via the bulk pipes |
jakowisp | 4:a95225ec39ac | 47 | * |
jakowisp | 4:a95225ec39ac | 48 | * @param ptp Pointer to the PTP device |
jakowisp | 4:a95225ec39ac | 49 | * @param buffer Pointer to the data recieved |
jakowisp | 4:a95225ec39ac | 50 | * @param length Total data received to be processed |
jakowisp | 4:a95225ec39ac | 51 | * |
jakowisp | 4:a95225ec39ac | 52 | * @return Void |
jakowisp | 4:a95225ec39ac | 53 | */ |
jakowisp | 0:ec1356628850 | 54 | void WriteObjectHandles(void *ptp,uint8_t *buffer,uint16_t length){ |
jakowisp | 0:ec1356628850 | 55 | int writeResult,errorcode; |
jakowisp | 0:ec1356628850 | 56 | uint16_t transferLength=length; |
jakowisp | 0:ec1356628850 | 57 | uint8_t *dataPtr=buffer; |
jakowisp | 0:ec1356628850 | 58 | |
jakowisp | 0:ec1356628850 | 59 | writeResult=fwrite(dataPtr,sizeof(uint8_t),transferLength,fp2); |
jakowisp | 0:ec1356628850 | 60 | if( writeResult != transferLength) { |
jakowisp | 0:ec1356628850 | 61 | errorcode=ferror(fp2); |
jakowisp | 0:ec1356628850 | 62 | if( errorcode ) |
jakowisp | 0:ec1356628850 | 63 | { |
jakowisp | 0:ec1356628850 | 64 | printf("\r\nError in writing to file %d\n",errorcode); |
jakowisp | 0:ec1356628850 | 65 | error("Yucky@!"); |
jakowisp | 0:ec1356628850 | 66 | } |
jakowisp | 0:ec1356628850 | 67 | } |
jakowisp | 0:ec1356628850 | 68 | } |
jakowisp | 0:ec1356628850 | 69 | |
jakowisp | 4:a95225ec39ac | 70 | /** |
jakowisp | 4:a95225ec39ac | 71 | * Test function 0x01 |
jakowisp | 4:a95225ec39ac | 72 | * |
jakowisp | 4:a95225ec39ac | 73 | * @param numberOfImages A pointer to where to write the images on the device |
jakowisp | 4:a95225ec39ac | 74 | * @param numberOfThumbs A pointer to where to write the images on the device |
jakowisp | 4:a95225ec39ac | 75 | * @return void |
jakowisp | 4:a95225ec39ac | 76 | */ |
jakowisp | 2:912d86148549 | 77 | void GetNumberOfThumbsAndImages(int *numberOfImages,int *numberOfThumbs){ |
jakowisp | 2:912d86148549 | 78 | uint32_t fileHandle=0,numImages=0; |
jakowisp | 2:912d86148549 | 79 | int internalNumberOfImages=0; |
jakowisp | 2:912d86148549 | 80 | int internalNumberOfThumbs=0; |
jakowisp | 2:912d86148549 | 81 | |
jakowisp | 2:912d86148549 | 82 | FILE *fp = fopen("/usb2/objHandles.bin", "rb"); |
jakowisp | 2:912d86148549 | 83 | fread(&numImages,sizeof(uint32_t),1,fp); |
jakowisp | 2:912d86148549 | 84 | while(numImages>0){ |
jakowisp | 2:912d86148549 | 85 | fread(&fileHandle,sizeof(uint32_t),1,fp); |
jakowisp | 3:1e2f56de7d5d | 86 | ptpdev->GetObjectInfo(fileHandle); |
jakowisp | 3:1e2f56de7d5d | 87 | |
jakowisp | 3:1e2f56de7d5d | 88 | if (ptpdev->objectInfo.thumbFormat == 0x3801 ) { |
jakowisp | 2:912d86148549 | 89 | internalNumberOfThumbs++; |
jakowisp | 2:912d86148549 | 90 | } |
jakowisp | 3:1e2f56de7d5d | 91 | if (ptpdev->objectInfo.objectFormat == 0x3801 ) { |
jakowisp | 2:912d86148549 | 92 | internalNumberOfImages++; |
jakowisp | 2:912d86148549 | 93 | } |
jakowisp | 2:912d86148549 | 94 | numImages--; |
jakowisp | 2:912d86148549 | 95 | } |
jakowisp | 2:912d86148549 | 96 | fclose(fp); |
jakowisp | 2:912d86148549 | 97 | *numberOfImages = internalNumberOfImages; |
jakowisp | 2:912d86148549 | 98 | *numberOfThumbs = internalNumberOfThumbs; |
jakowisp | 2:912d86148549 | 99 | |
jakowisp | 2:912d86148549 | 100 | } |
jakowisp | 2:912d86148549 | 101 | |
jakowisp | 4:a95225ec39ac | 102 | /** |
jakowisp | 4:a95225ec39ac | 103 | * Retrieve all thumbnail images and real images that are JPG files. |
jakowisp | 4:a95225ec39ac | 104 | */ |
jakowisp | 3:1e2f56de7d5d | 105 | void GetAllImagesAndThumbs(void) { |
jakowisp | 0:ec1356628850 | 106 | FILE *fp; |
jakowisp | 0:ec1356628850 | 107 | |
jakowisp | 0:ec1356628850 | 108 | uint32_t fileHandle=0,numImages=0; |
jakowisp | 0:ec1356628850 | 109 | |
jakowisp | 3:1e2f56de7d5d | 110 | printf("objectid,objectinfosize,imagetype,thumbtype\r\n"); |
jakowisp | 3:1e2f56de7d5d | 111 | fp = fopen("/usb2/objHandles.bin", "rb"); |
jakowisp | 0:ec1356628850 | 112 | |
jakowisp | 0:ec1356628850 | 113 | fread(&numImages,sizeof(uint32_t),1,fp); |
jakowisp | 0:ec1356628850 | 114 | while(numImages>0){ |
jakowisp | 3:1e2f56de7d5d | 115 | fread(&fileHandle,sizeof(uint32_t),1,fp); |
jakowisp | 3:1e2f56de7d5d | 116 | ptpdev->GetObjectInfo(fileHandle); |
jakowisp | 4:a95225ec39ac | 117 | printf("%ld,%x,%x,%x\r\n",numImages,fileHandle,ptpdev->objectInfo.objectFormat,ptpdev->objectInfo.thumbFormat); |
jakowisp | 3:1e2f56de7d5d | 118 | |
jakowisp | 3:1e2f56de7d5d | 119 | if (ptpdev->objectInfo.thumbFormat == 0x3801 && numImages < 864 ) { |
jakowisp | 3:1e2f56de7d5d | 120 | sprintf(fname,"/usb2/thumb_%s",ptpdev->objectInfo.filename.getString()); |
jakowisp | 3:1e2f56de7d5d | 121 | fp2 = fopen(fname, "wb"); |
jakowisp | 0:ec1356628850 | 122 | printf("Starting transfer of %s\r\n",fname); |
jakowisp | 3:1e2f56de7d5d | 123 | ptpdev->GetThumb(fileHandle,(void *)&WriteObjectHandles); |
jakowisp | 0:ec1356628850 | 124 | fclose(fp2); |
jakowisp | 0:ec1356628850 | 125 | printf("GetThumb Transaction Complete\r\n"); |
jakowisp | 0:ec1356628850 | 126 | } |
jakowisp | 0:ec1356628850 | 127 | |
jakowisp | 3:1e2f56de7d5d | 128 | if (ptpdev->objectInfo.objectFormat == 0x3801 && numImages < 864 ) { |
jakowisp | 3:1e2f56de7d5d | 129 | sprintf(fname,"/usb2/%s",ptpdev->objectInfo.filename.getString()); |
jakowisp | 3:1e2f56de7d5d | 130 | printf("%s -Type: 0x%04x\r\n",fname,ptpdev->objectInfo.objectFormat); |
jakowisp | 0:ec1356628850 | 131 | printf("Starting transfer of %s\r\n",fname); |
jakowisp | 2:912d86148549 | 132 | fp2 = fopen(fname, "wb"); |
jakowisp | 3:1e2f56de7d5d | 133 | ptpdev->GetObject(fileHandle,(void *)&WriteObjectHandles); |
jakowisp | 0:ec1356628850 | 134 | fclose(fp2); |
jakowisp | 2:912d86148549 | 135 | printf("GetObject Transaction Complete\r\n"); |
jakowisp | 0:ec1356628850 | 136 | } |
jakowisp | 0:ec1356628850 | 137 | numImages--; |
jakowisp | 0:ec1356628850 | 138 | } |
jakowisp | 0:ec1356628850 | 139 | fclose(fp); |
jakowisp | 3:1e2f56de7d5d | 140 | } |
jakowisp | 2:912d86148549 | 141 | |
jakowisp | 4:a95225ec39ac | 142 | /** |
jakowisp | 4:a95225ec39ac | 143 | * Thread to Watch for MSD image |
jakowisp | 4:a95225ec39ac | 144 | */ |
jakowisp | 3:1e2f56de7d5d | 145 | void msd_task(void const *) { |
jakowisp | 3:1e2f56de7d5d | 146 | USBHostMSD msd2("usb2"); |
jakowisp | 3:1e2f56de7d5d | 147 | |
jakowisp | 3:1e2f56de7d5d | 148 | msddev=&msd2; |
jakowisp | 3:1e2f56de7d5d | 149 | while(true) { |
jakowisp | 3:1e2f56de7d5d | 150 | while(!msd2.connect()) { |
jakowisp | 3:1e2f56de7d5d | 151 | Thread::wait(500); |
jakowisp | 3:1e2f56de7d5d | 152 | } |
jakowisp | 3:1e2f56de7d5d | 153 | |
jakowisp | 3:1e2f56de7d5d | 154 | DIR *dp; |
jakowisp | 3:1e2f56de7d5d | 155 | struct dirent *ep; |
jakowisp | 3:1e2f56de7d5d | 156 | dp = opendir ("/usb2"); |
jakowisp | 3:1e2f56de7d5d | 157 | |
jakowisp | 3:1e2f56de7d5d | 158 | if (dp != NULL) |
jakowisp | 3:1e2f56de7d5d | 159 | { |
jakowisp | 3:1e2f56de7d5d | 160 | ep = readdir (dp); |
jakowisp | 3:1e2f56de7d5d | 161 | while (ep!=NULL) { |
jakowisp | 3:1e2f56de7d5d | 162 | printf("%s\r\n",ep->d_name); |
jakowisp | 3:1e2f56de7d5d | 163 | ep = readdir (dp); |
jakowisp | 3:1e2f56de7d5d | 164 | } |
jakowisp | 3:1e2f56de7d5d | 165 | (void) closedir (dp); |
jakowisp | 3:1e2f56de7d5d | 166 | } |
jakowisp | 3:1e2f56de7d5d | 167 | |
jakowisp | 3:1e2f56de7d5d | 168 | while(msd2.connect()) { |
jakowisp | 3:1e2f56de7d5d | 169 | Thread::wait(500); |
jakowisp | 3:1e2f56de7d5d | 170 | } |
jakowisp | 3:1e2f56de7d5d | 171 | } |
jakowisp | 3:1e2f56de7d5d | 172 | } |
jakowisp | 3:1e2f56de7d5d | 173 | |
jakowisp | 4:a95225ec39ac | 174 | /** |
jakowisp | 4:a95225ec39ac | 175 | * Function TO be called by the menu system to start the execution thread to execute the call. |
jakowisp | 4:a95225ec39ac | 176 | */ |
jakowisp | 3:1e2f56de7d5d | 177 | void SetCommandGETALLJPG(void) { |
jakowisp | 3:1e2f56de7d5d | 178 | command=GETALLJPG; |
jakowisp | 3:1e2f56de7d5d | 179 | } |
jakowisp | 3:1e2f56de7d5d | 180 | |
jakowisp | 4:a95225ec39ac | 181 | /** |
jakowisp | 4:a95225ec39ac | 182 | * Function to display status during image transfers |
jakowisp | 4:a95225ec39ac | 183 | */ |
jakowisp | 3:1e2f56de7d5d | 184 | void GetAllJPGStatus(void) { |
jakowisp | 3:1e2f56de7d5d | 185 | led=!led; |
jakowisp | 3:1e2f56de7d5d | 186 | lcd.cls(); |
jakowisp | 3:1e2f56de7d5d | 187 | if(ptpdev->dataLeftToTransfer>0) { |
jakowisp | 3:1e2f56de7d5d | 188 | lcd.locate(10,0); |
jakowisp | 3:1e2f56de7d5d | 189 | lcd.printf("%ld/%ld", ptpdev->dataLeftToTransfer, ptpdev->totalDataToTransfer); |
jakowisp | 3:1e2f56de7d5d | 190 | lcd.locate(0,10); |
jakowisp | 3:1e2f56de7d5d | 191 | lcd.printf("%s",fname); |
jakowisp | 3:1e2f56de7d5d | 192 | } |
jakowisp | 3:1e2f56de7d5d | 193 | } |
jakowisp | 3:1e2f56de7d5d | 194 | |
jakowisp | 4:a95225ec39ac | 195 | /** |
jakowisp | 4:a95225ec39ac | 196 | * Thread to watch for the PTP device connected, and commands that need to be executed. |
jakowisp | 4:a95225ec39ac | 197 | */ |
jakowisp | 3:1e2f56de7d5d | 198 | void ptp_task2(void const *) { |
jakowisp | 3:1e2f56de7d5d | 199 | USBHostPTP ptp; |
jakowisp | 3:1e2f56de7d5d | 200 | ptpdev=&ptp; |
jakowisp | 3:1e2f56de7d5d | 201 | |
jakowisp | 3:1e2f56de7d5d | 202 | int numi,numt; |
jakowisp | 3:1e2f56de7d5d | 203 | uint32_t objCount=0; |
jakowisp | 3:1e2f56de7d5d | 204 | |
jakowisp | 3:1e2f56de7d5d | 205 | while(true) { |
jakowisp | 3:1e2f56de7d5d | 206 | while(!ptpdev->connect()) { |
jakowisp | 3:1e2f56de7d5d | 207 | Thread::wait(500); |
jakowisp | 3:1e2f56de7d5d | 208 | } |
jakowisp | 3:1e2f56de7d5d | 209 | |
jakowisp | 3:1e2f56de7d5d | 210 | while(!msddev->connected()){ |
jakowisp | 3:1e2f56de7d5d | 211 | Thread::wait(500); |
jakowisp | 3:1e2f56de7d5d | 212 | } |
jakowisp | 4:a95225ec39ac | 213 | |
jakowisp | 4:a95225ec39ac | 214 | /* after device connected open a session, get device information, and object handles |
jakowisp | 4:a95225ec39ac | 215 | */ |
jakowisp | 3:1e2f56de7d5d | 216 | ptp.OpenSession(); |
jakowisp | 3:1e2f56de7d5d | 217 | printf("OpenSession Transaction Complete\r\n\r\n"); |
jakowisp | 3:1e2f56de7d5d | 218 | ptp.GetDeviceInfo(); |
jakowisp | 3:1e2f56de7d5d | 219 | printf("GetDeviceInfo Transaction Complete\r\n"); |
jakowisp | 3:1e2f56de7d5d | 220 | fp2 = fopen("/usb2/objHandles.bin", "wb"); |
jakowisp | 3:1e2f56de7d5d | 221 | ptp.GetObjectHandles(0xffffffff,0x0000,0x0000,(void *)&WriteObjectHandles); |
jakowisp | 3:1e2f56de7d5d | 222 | fclose(fp2); |
jakowisp | 3:1e2f56de7d5d | 223 | printf("GetObjecthandles Transaction Complete\r\n"); |
jakowisp | 3:1e2f56de7d5d | 224 | |
jakowisp | 4:a95225ec39ac | 225 | //While ptp device connected watch for commands. |
jakowisp | 3:1e2f56de7d5d | 226 | while(ptpdev->connected()) { |
jakowisp | 3:1e2f56de7d5d | 227 | commandActive=true; |
jakowisp | 3:1e2f56de7d5d | 228 | switch(command) { |
jakowisp | 3:1e2f56de7d5d | 229 | case GETALLJPG: |
jakowisp | 3:1e2f56de7d5d | 230 | statusFunction=&GetAllJPGStatus; |
jakowisp | 3:1e2f56de7d5d | 231 | GetAllImagesAndThumbs(); |
jakowisp | 3:1e2f56de7d5d | 232 | statusFunction=NULL; |
jakowisp | 3:1e2f56de7d5d | 233 | break; |
jakowisp | 3:1e2f56de7d5d | 234 | case GETALLJPGTHUMB: |
jakowisp | 3:1e2f56de7d5d | 235 | break; |
jakowisp | 3:1e2f56de7d5d | 236 | case GETNUMJPG: |
jakowisp | 3:1e2f56de7d5d | 237 | GetNumberOfThumbsAndImages(&numi,&numt); |
jakowisp | 3:1e2f56de7d5d | 238 | printf("images: %d, thumbs:%d\r\n",numi,numt); |
jakowisp | 3:1e2f56de7d5d | 239 | break; |
jakowisp | 3:1e2f56de7d5d | 240 | case GETNUMOBJ: |
jakowisp | 3:1e2f56de7d5d | 241 | ptp.GetNumObjects(&objCount); |
jakowisp | 3:1e2f56de7d5d | 242 | printf("GetNumObjects Transaction Complete - Count:%ld\r\n",objCount); |
jakowisp | 3:1e2f56de7d5d | 243 | break; |
jakowisp | 3:1e2f56de7d5d | 244 | case DUMPDEVICEINFO: |
jakowisp | 3:1e2f56de7d5d | 245 | ptp.DumpDeviceInfo(); |
jakowisp | 3:1e2f56de7d5d | 246 | break; |
jakowisp | 3:1e2f56de7d5d | 247 | case CLOSESESSION: |
jakowisp | 3:1e2f56de7d5d | 248 | ptpdev->CloseSession(); |
jakowisp | 3:1e2f56de7d5d | 249 | printf("CloseSession Transaction Complete\r\n"); |
jakowisp | 3:1e2f56de7d5d | 250 | break; |
jakowisp | 3:1e2f56de7d5d | 251 | default: |
jakowisp | 3:1e2f56de7d5d | 252 | commandActive=false; |
jakowisp | 3:1e2f56de7d5d | 253 | break; |
jakowisp | 3:1e2f56de7d5d | 254 | } |
jakowisp | 3:1e2f56de7d5d | 255 | command=0x00; |
jakowisp | 3:1e2f56de7d5d | 256 | Thread::wait(100); |
jakowisp | 0:ec1356628850 | 257 | } |
jakowisp | 0:ec1356628850 | 258 | } |
jakowisp | 0:ec1356628850 | 259 | } |
jakowisp | 0:ec1356628850 | 260 | |
jakowisp | 4:a95225ec39ac | 261 | ///Menu function to set the Command to be executed. |
jakowisp | 3:1e2f56de7d5d | 262 | void SetCommandGETNUMJPG(void) { |
jakowisp | 3:1e2f56de7d5d | 263 | command=GETNUMJPG; |
jakowisp | 3:1e2f56de7d5d | 264 | } |
jakowisp | 3:1e2f56de7d5d | 265 | |
jakowisp | 4:a95225ec39ac | 266 | ///Menu function to set the Command to be executed. |
jakowisp | 3:1e2f56de7d5d | 267 | void SetCommandGETNUMOBJ(void) { |
jakowisp | 3:1e2f56de7d5d | 268 | command=GETNUMOBJ; |
jakowisp | 3:1e2f56de7d5d | 269 | } |
jakowisp | 3:1e2f56de7d5d | 270 | |
jakowisp | 4:a95225ec39ac | 271 | ///Menu function to set the Command to be executed. |
jakowisp | 3:1e2f56de7d5d | 272 | void SetCommandDUMPDEVICEINFO(void) { |
jakowisp | 3:1e2f56de7d5d | 273 | command=DUMPDEVICEINFO; |
jakowisp | 3:1e2f56de7d5d | 274 | } |
jakowisp | 3:1e2f56de7d5d | 275 | |
jakowisp | 4:a95225ec39ac | 276 | ///Menu function to set the Command to be executed. |
jakowisp | 3:1e2f56de7d5d | 277 | void SetCommandCLOSESESSION(void) { |
jakowisp | 3:1e2f56de7d5d | 278 | command=CLOSESESSION; |
jakowisp | 3:1e2f56de7d5d | 279 | } |
jakowisp | 3:1e2f56de7d5d | 280 | |
jakowisp | 4:a95225ec39ac | 281 | ///Main fuction to display the Status of the application. |
jakowisp | 0:ec1356628850 | 282 | int main() { |
jakowisp | 0:ec1356628850 | 283 | lcd.cls(); |
jakowisp | 0:ec1356628850 | 284 | lcd.locate(10,3); |
jakowisp | 0:ec1356628850 | 285 | lcd.printf("Initializing"); |
jakowisp | 3:1e2f56de7d5d | 286 | Thread ptpTask2(ptp_task2, NULL, osPriorityNormal, 1024 * 4); |
jakowisp | 3:1e2f56de7d5d | 287 | Thread msdTask2(msd_task, NULL, osPriorityNormal, 1024 * 4); |
jakowisp | 3:1e2f56de7d5d | 288 | Menu rootMenu("root"); |
jakowisp | 3:1e2f56de7d5d | 289 | Menu testMenu("Test menu"); |
jakowisp | 3:1e2f56de7d5d | 290 | testMenu.add(Selection(&SetCommandDUMPDEVICEINFO, 2, NULL, "Dump Device Info")); // The function argument of selection can be added directly |
jakowisp | 3:1e2f56de7d5d | 291 | testMenu.add(Selection(&SetCommandGETALLJPG, 2, NULL, "Get All Images")); // The function argument of selection can be added directly |
jakowisp | 3:1e2f56de7d5d | 292 | testMenu.add(Selection(&SetCommandGETNUMOBJ, 1, NULL, "Get Number of Objects")); |
jakowisp | 3:1e2f56de7d5d | 293 | testMenu.add(Selection(&SetCommandGETNUMJPG, 3, NULL, "Get Number of Images")); |
jakowisp | 3:1e2f56de7d5d | 294 | //testMenu.add(Selection(NULL, 4, NULL, "Get Number of Thumbnails")); |
jakowisp | 3:1e2f56de7d5d | 295 | //testMenu.add(Selection(NULL, 5, NULL, "Get Number of Thumbnails")); |
jakowisp | 3:1e2f56de7d5d | 296 | testMenu.add(Selection(&SetCommandCLOSESESSION, 4, NULL, "Close Session")); |
jakowisp | 3:1e2f56de7d5d | 297 | testMenu.add(Selection(NULL, 5, &rootMenu, " Go back")); // always add a Selection at the end to point to the parent |
jakowisp | 4:a95225ec39ac | 298 | Menu aboutMenu("About Menu"); // about menu |
jakowisp | 3:1e2f56de7d5d | 299 | aboutMenu.add(Selection(NULL, 0, NULL, "Author:")); |
jakowisp | 3:1e2f56de7d5d | 300 | aboutMenu.add(Selection(NULL, 1, NULL, " Dwayne S Dilbeck")); |
jakowisp | 3:1e2f56de7d5d | 301 | aboutMenu.add(Selection(NULL, 2, NULL, " 8/29/2013")); |
jakowisp | 3:1e2f56de7d5d | 302 | aboutMenu.add(Selection(NULL, 3, NULL, " USB Device Interface:")); |
jakowisp | 3:1e2f56de7d5d | 303 | aboutMenu.add(Selection(NULL, 4, NULL, " Architecture,")); |
jakowisp | 3:1e2f56de7d5d | 304 | aboutMenu.add(Selection(NULL, 5, NULL, " Protocols,")); |
jakowisp | 3:1e2f56de7d5d | 305 | aboutMenu.add(Selection(NULL, 6, NULL, " and programming.")); |
jakowisp | 3:1e2f56de7d5d | 306 | aboutMenu.add(Selection(NULL, 7, &rootMenu, " Go back")); |
jakowisp | 3:1e2f56de7d5d | 307 | rootMenu.add(Selection(NULL, 0, &testMenu, "TEST MENU")); |
jakowisp | 3:1e2f56de7d5d | 308 | rootMenu.add(Selection(NULL, 1, &aboutMenu, "About menu")); |
jakowisp | 3:1e2f56de7d5d | 309 | Navigator navigator(&rootMenu, &lcd); |
jakowisp | 3:1e2f56de7d5d | 310 | |
jakowisp | 0:ec1356628850 | 311 | while(1) { |
jakowisp | 5:013bdb272a9c | 312 | if(ptpdev != NULL) { |
jakowisp | 3:1e2f56de7d5d | 313 | if(ptpdev->connected()) { |
jakowisp | 3:1e2f56de7d5d | 314 | if(!commandActive) { |
jakowisp | 3:1e2f56de7d5d | 315 | navigator.poll(); |
jakowisp | 3:1e2f56de7d5d | 316 | } else { |
jakowisp | 5:013bdb272a9c | 317 | if(statusFunction != NULL) |
jakowisp | 3:1e2f56de7d5d | 318 | (*statusFunction)(); |
jakowisp | 3:1e2f56de7d5d | 319 | else { |
jakowisp | 5:013bdb272a9c | 320 | lcd.cls(); |
jakowisp | 5:013bdb272a9c | 321 | wait_ms(20); |
jakowisp | 3:1e2f56de7d5d | 322 | } |
jakowisp | 3:1e2f56de7d5d | 323 | } |
jakowisp | 3:1e2f56de7d5d | 324 | |
jakowisp | 3:1e2f56de7d5d | 325 | } else { |
jakowisp | 3:1e2f56de7d5d | 326 | lcd.cls(); |
jakowisp | 3:1e2f56de7d5d | 327 | lcd.locate(10,3); |
jakowisp | 3:1e2f56de7d5d | 328 | lcd.printf("Please connect PTP device."); |
jakowisp | 3:1e2f56de7d5d | 329 | } |
jakowisp | 3:1e2f56de7d5d | 330 | } |
jakowisp | 3:1e2f56de7d5d | 331 | Thread::wait(200); |
jakowisp | 0:ec1356628850 | 332 | } |
jakowisp | 0:ec1356628850 | 333 | } |
jakowisp | 0:ec1356628850 | 334 | |
jakowisp | 0:ec1356628850 | 335 | |
jakowisp | 0:ec1356628850 | 336 | |
jakowisp | 0:ec1356628850 | 337 |