[3587f7f] | 1 | /* HEREPIC - AVR based ICSP programmer for 16F6xx and 16F8xx chips
|
---|
| 2 | * Copyright 2012, Adrien Destugues <pulkomandy@gmail.com>
|
---|
| 3 | *
|
---|
| 4 | * This file is distributed under the terms of the MIT licence
|
---|
| 5 | */
|
---|
| 6 |
|
---|
[f0689d3] | 7 | // C++
|
---|
| 8 | #include <iostream>
|
---|
| 9 |
|
---|
| 10 | // POSIX
|
---|
| 11 | #include <semaphore.h>
|
---|
| 12 | #include <unistd.h>
|
---|
| 13 |
|
---|
| 14 | // Haiku
|
---|
| 15 | #include <USBKit.h>
|
---|
| 16 |
|
---|
| 17 |
|
---|
| 18 | // We need a subclass of USBRoster to enumerate devices. The Deviceadded hook
|
---|
| 19 | // will be called for all plugged devices. If we don't find the correct one,
|
---|
| 20 | // it will also be called later, as devices are plugged. So we can wait for the
|
---|
| 21 | // right device to come in !
|
---|
| 22 | class MyUSBRoster: public BUSBRoster {
|
---|
| 23 | public:
|
---|
| 24 | MyUSBRoster(BUSBDevice*& device, sem_t& deviceLock)
|
---|
| 25 | : fDevice(device)
|
---|
| 26 | , fDeviceLock(deviceLock)
|
---|
| 27 | {
|
---|
| 28 | Start();
|
---|
| 29 | }
|
---|
| 30 |
|
---|
| 31 | ~MyUSBRoster()
|
---|
| 32 | {
|
---|
| 33 | sem_destroy(&fDeviceLock);
|
---|
| 34 | Stop();
|
---|
| 35 | }
|
---|
| 36 |
|
---|
| 37 | status_t DeviceAdded(BUSBDevice* device)
|
---|
| 38 | {
|
---|
| 39 | if(device->VendorID() == 0x16c0 && device->ProductID() == 0x05DC
|
---|
| 40 | && strcmp(device->ManufacturerString(), "pulkomandy.tk") == 0
|
---|
| 41 | && strcmp(device->ProductString(), "HerePic") == 0)
|
---|
| 42 | {
|
---|
| 43 | std::cout << "Programmer found !" << std::endl;
|
---|
| 44 | // TODO send message to main app to tell it we're ready to go.
|
---|
| 45 | fDevice = device;
|
---|
| 46 | sem_post(&fDeviceLock);
|
---|
| 47 | }
|
---|
| 48 | return B_OK;
|
---|
| 49 | }
|
---|
| 50 |
|
---|
| 51 | void DeviceRemoved(BUSBDevice* device)
|
---|
| 52 | {
|
---|
| 53 | // TODO send message to main app to tell there's a problem !
|
---|
| 54 | // or we may even commit suicide at this point...
|
---|
| 55 | }
|
---|
| 56 | private:
|
---|
| 57 | BUSBDevice*& fDevice;
|
---|
| 58 | sem_t& fDeviceLock;
|
---|
| 59 | };
|
---|
| 60 |
|
---|
| 61 |
|
---|
| 62 | void usage(const char* progname)
|
---|
| 63 | {
|
---|
| 64 | // print usage
|
---|
| 65 | std::cout << progname << " - AVR based ICSP programmer for "
|
---|
| 66 | "PIC16F62x and PIC16F87x" << std::endl <<
|
---|
| 67 | "Written by Adrien Destugues <pulkomandy@gmail.com>"
|
---|
| 68 | << std::endl << std::endl <<
|
---|
| 69 | "Usage:" << std::endl <<
|
---|
| 70 | " -w file.hex Write file to device" << std::endl <<
|
---|
| 71 | " -r file.hex Read device to file" << std::endl <<
|
---|
| 72 | " -e Erase device" << std::endl <<
|
---|
| 73 | " -h Display this help message" << std::endl;
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 |
|
---|
[3587f7f] | 77 | int main(int argc, char** argv)
|
---|
| 78 | {
|
---|
[f0689d3] | 79 | // parse CLI args
|
---|
| 80 | static const char* optstring = ":w:r:eh";
|
---|
| 81 |
|
---|
| 82 | int nextopt;
|
---|
| 83 | signed char action = 0;
|
---|
| 84 | const char* filename;
|
---|
| 85 |
|
---|
| 86 | do {
|
---|
| 87 | nextopt = getopt(argc,argv, optstring);
|
---|
| 88 |
|
---|
| 89 | switch(nextopt)
|
---|
| 90 | {
|
---|
| 91 | case 'w':
|
---|
| 92 | case 'r':
|
---|
| 93 | case 'h':
|
---|
| 94 | case 'e':
|
---|
| 95 | // We get the filename in all cases, for h and e it will give
|
---|
| 96 | // meaningless results but we won't be using it anyway
|
---|
| 97 | filename = optarg;
|
---|
| 98 | // store the action, but make sure we do it only once
|
---|
| 99 | if (action > 0)
|
---|
| 100 | {
|
---|
| 101 | std::cerr << "multiple actions specified (only one of w,r,e is allowed)" << std::endl;
|
---|
| 102 | action = -1;
|
---|
| 103 | } else {
|
---|
| 104 | action = nextopt;
|
---|
| 105 | }
|
---|
| 106 | break;
|
---|
| 107 | case ':':
|
---|
| 108 | std::cout << "option -" << (char)optopt << " needs an argument" << std::endl;
|
---|
| 109 | break;
|
---|
| 110 | case '?':
|
---|
| 111 | std::cerr << "Unknown option: -" << (char)optopt << std::endl;
|
---|
| 112 | break;
|
---|
| 113 | case -1:
|
---|
| 114 | // end of options
|
---|
| 115 | break;
|
---|
| 116 | default:
|
---|
| 117 | std::cerr << "Command-line format error at argument " << optind
|
---|
| 118 | << std::endl;
|
---|
| 119 | break;
|
---|
| 120 | }
|
---|
| 121 | } while(nextopt != -1);
|
---|
| 122 |
|
---|
| 123 | if (action <= 0)
|
---|
| 124 | {
|
---|
| 125 | usage(argv[0]);
|
---|
| 126 | exit(action);
|
---|
| 127 | }
|
---|
| 128 |
|
---|
[3587f7f] | 129 | // TODO take action depending on command request in CLI
|
---|
| 130 | // TODO handle the boring usb stuff... (might be nice to abstract it so we
|
---|
| 131 | // can use both libusb and haiku usb kit)
|
---|
[f0689d3] | 132 |
|
---|
| 133 | BUSBDevice* theDevice = NULL;
|
---|
| 134 | sem_t deviceLock;
|
---|
| 135 |
|
---|
| 136 | sem_init(&deviceLock, false, 0);
|
---|
| 137 |
|
---|
| 138 | MyUSBRoster usbRoster(theDevice, deviceLock);
|
---|
| 139 | usbRoster.Start();
|
---|
| 140 |
|
---|
| 141 | int deviceAvailable;
|
---|
| 142 | sem_getvalue(&deviceLock, &deviceAvailable);
|
---|
| 143 | if(deviceAvailable == 0)
|
---|
| 144 | {
|
---|
| 145 | std::cout << "Programmer not connected. Waiting for it..." << std::endl;
|
---|
| 146 | }
|
---|
| 147 |
|
---|
| 148 | sem_wait(&deviceLock);
|
---|
| 149 |
|
---|
| 150 | // Here, perform the programming cycle !
|
---|
| 151 | switch(action)
|
---|
| 152 | {
|
---|
| 153 | case 'r':
|
---|
| 154 | case 'w':
|
---|
| 155 | case 'e':
|
---|
| 156 | ;
|
---|
| 157 | }
|
---|
[3587f7f] | 158 | }
|
---|