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 |
|
---|
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 |
|
---|
77 | int main(int argc, char** argv)
|
---|
78 | {
|
---|
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 |
|
---|
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)
|
---|
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 | }
|
---|
158 | }
|
---|