You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

312 lines
5.8KB

  1. #pragma once
  2. #ifdef LAUNCHPAD
  3. #include <memory.h>
  4. #include <windows.h>
  5. #include "driver_include.hpp"
  6. #pragma pack(push,1)
  7. struct __attribute__((aligned(1), packed)) _launchpadMessage
  8. {
  9. uint8_t status;
  10. uint8_t cmd;
  11. uint8_t key;
  12. uint8_t currentScene;
  13. uint8_t lpNumber;
  14. uint8_t shiftDown;
  15. short param0;
  16. short param1;
  17. #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
  18. void FromMessage(LaunchpadMessage *src)
  19. {
  20. status = (uint8_t)src->status;
  21. cmd = (uint8_t)src->cmd;
  22. key = (uint8_t)src->key;
  23. currentScene = (uint8_t)src->currentScene;
  24. lpNumber = (uint8_t)src->lpNumber;
  25. shiftDown = (uint8_t)(src->shiftDown ? 1 : 0);
  26. param0 = src->param0;
  27. param1 = src->param1;
  28. }
  29. LaunchpadMessage Reconstruct()
  30. {
  31. LaunchpadMessage rv;
  32. rv.status = (LaunchpadKeyStatus)status;
  33. rv.cmd = (LaunchpadCommand)cmd;
  34. rv.key = (LaunchpadKey)key;
  35. rv.currentScene = (LaunchpadScene)currentScene;
  36. rv.lpNumber = lpNumber;
  37. rv.shiftDown = shiftDown != 0;
  38. rv.param0 = param0;
  39. rv.param1 = param1;
  40. return rv;
  41. }
  42. };
  43. #pragma pack(pop)
  44. class communicator
  45. {
  46. private:
  47. class circBuffer
  48. {
  49. private:
  50. uint8_t * mapAccess;
  51. int rdPtr;
  52. int WR_PTR_POS;
  53. int P0;
  54. int PN;
  55. public:
  56. static int bufferOverhead() { return sizeof(uint32_t); } // n. di bytes EXTRA richiesti per la gestione del buffer circolare
  57. void Clear()
  58. {
  59. rdPtr = wrPtr_get();
  60. }
  61. circBuffer(int bufferSize, void *acc, int offset)
  62. {
  63. WR_PTR_POS = offset;
  64. P0 = WR_PTR_POS + bufferOverhead(); // posizione 0 memoria effettiva (dove salvare e leggere i dati, dopo i primi 8 bytes riservati ai puntatori rd/wr)
  65. PN = P0 + bufferSize - bufferOverhead();
  66. mapAccess = (uint8_t*)acc;
  67. Clear();
  68. }
  69. ~circBuffer()
  70. {
  71. mapAccess = NULL;
  72. }
  73. void WriteChunk(LaunchpadMessage *_msg)
  74. {
  75. #ifdef DEBUG
  76. info("send message %i; tx size is %i", _msg->cmd, sizeof(_launchpadMessage));
  77. #endif
  78. _launchpadMessage msg;
  79. msg.FromMessage(_msg);
  80. uint8_t *ptr = (uint8_t *)&msg;
  81. int cur_wrPtr = wrPtr_get();
  82. for(int k = 0; k < (int)sizeof(_launchpadMessage); k++)
  83. cur_wrPtr = Put(*ptr++, cur_wrPtr);
  84. wrPtr_set(cur_wrPtr); // finalizza IN SOLIDO il chunk appena letto
  85. }
  86. LaunchpadMessage ReadChunk()
  87. {
  88. if(data_available())
  89. {
  90. _launchpadMessage msg;
  91. uint8_t *p = (uint8_t *)&msg;
  92. for(int k = 0; k < (int)sizeof(_launchpadMessage); k++)
  93. *p++ = Get();
  94. return msg.Reconstruct();
  95. }
  96. LaunchpadMessage rv;
  97. rv.status = LaunchpadKeyStatus::keyNone;
  98. return rv;
  99. }
  100. private:
  101. int wrPtr_get()
  102. {
  103. return *((uint32_t *)(mapAccess + WR_PTR_POS));
  104. }
  105. void wrPtr_set(uint32_t v)
  106. {
  107. uint32_t *ptr = (uint32_t *)(mapAccess + WR_PTR_POS);
  108. *ptr = v;
  109. }
  110. bool data_available() { return rdPtr != wrPtr_get(); }
  111. int incPtr(int ptr)
  112. {
  113. if(++ptr >= PN)
  114. ptr = P0;
  115. return ptr;
  116. }
  117. int Put(uint8_t b, int ptr)
  118. {
  119. mapAccess[ptr] = b;
  120. return incPtr(ptr);
  121. }
  122. uint8_t Get()
  123. {
  124. int trdPtr = rdPtr;
  125. uint8_t rv = mapAccess[trdPtr];
  126. rdPtr = incPtr(trdPtr);
  127. return rv;
  128. }
  129. };
  130. public:
  131. communicator()
  132. {
  133. hMapFile = NULL;
  134. syncMutex = NULL;
  135. pmemory = NULL;
  136. pCommonMemory = NULL;
  137. rdBuffer = wrBuffer = NULL;
  138. }
  139. ~communicator()
  140. {
  141. deinit();
  142. }
  143. void clear()
  144. {
  145. if(pmemory != NULL)
  146. {
  147. rdBuffer->Clear();
  148. wrBuffer->Clear();
  149. }
  150. }
  151. bool Connected() { return pmemory != NULL; }
  152. bool Open()
  153. {
  154. if(pmemory == NULL)
  155. {
  156. try
  157. {
  158. init();
  159. } catch(_exception ex)
  160. {
  161. deinit();
  162. }
  163. }
  164. return pmemory != NULL;
  165. }
  166. void Write(LaunchpadMessage msg)
  167. {
  168. if(checkServer())
  169. {
  170. if(WaitForSingleObject(syncMutex, 500) == WAIT_OBJECT_0)
  171. {
  172. wrBuffer->WriteChunk(&msg);
  173. ReleaseMutex(syncMutex);
  174. }
  175. }
  176. }
  177. LaunchpadMessage Read()
  178. {
  179. if(checkServer())
  180. return rdBuffer->ReadChunk();
  181. LaunchpadMessage rv;
  182. rv.status = LaunchpadKeyStatus::keyNone;
  183. return rv;
  184. }
  185. private:
  186. void *pmemory;
  187. uint32_t *pCommonMemory;
  188. circBuffer *rdBuffer;
  189. circBuffer *wrBuffer;
  190. HANDLE hMapFile;
  191. HANDLE syncMutex;
  192. void init()
  193. {
  194. const int BUFFER_SIZE = 100;
  195. const int SERVERUP_POS = 0; // (Int32) : indica se il server e' up o down
  196. const int START_OF_BUFFER = SERVERUP_POS + sizeof(uint32_t); // prima locazione di memoria utile per il buffer circolare
  197. int b_l = BUFFER_SIZE * sizeof(_launchpadMessage) + circBuffer::bufferOverhead();
  198. #ifdef DEBUG
  199. info("Open file mapping");
  200. #endif
  201. hMapFile = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, TRUE, "launchpad_mem");
  202. if(hMapFile != NULL)
  203. {
  204. #ifdef DEBUG
  205. info("file mapping opened");
  206. #endif
  207. void *p = MapViewOfFile(hMapFile, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 2 * b_l + sizeof(uint32_t)/*flag SERVER_POS*/);
  208. #ifdef DEBUG
  209. info("MapViewOfFile success");
  210. #endif
  211. syncMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "launchpad_mtx");
  212. #ifdef DEBUG
  213. if(syncMutex != NULL) info("mutex OK"); else info("*** no mutexxxxxxx!!!!!! ****");
  214. #endif
  215. wrBuffer = new circBuffer(b_l, p, START_OF_BUFFER);
  216. rdBuffer = new circBuffer(b_l, p, START_OF_BUFFER + b_l);
  217. #ifdef DEBUG
  218. info("circBuffer created");
  219. #endif
  220. pmemory = p;
  221. pCommonMemory = (uint32_t *)p;
  222. #ifdef DEBUG
  223. info("Opened OK");
  224. #endif
  225. }
  226. }
  227. bool checkServer()
  228. {
  229. bool rv = false;
  230. if(pCommonMemory != NULL)
  231. {
  232. uint32_t server = *pCommonMemory;
  233. if(server == 0)
  234. {
  235. #ifdef DEBUG
  236. info("*** connection lost ***");
  237. #endif
  238. deinit();
  239. } else
  240. rv = true;
  241. }
  242. return rv;
  243. }
  244. void deinit()
  245. {
  246. void *p = pmemory;
  247. pmemory = NULL;
  248. pCommonMemory = NULL;
  249. if(p != NULL)
  250. UnmapViewOfFile(p);
  251. if(hMapFile != NULL)
  252. CloseHandle(hMapFile);
  253. hMapFile = NULL;
  254. if(rdBuffer != NULL)
  255. {
  256. delete rdBuffer;
  257. rdBuffer = NULL;
  258. }
  259. if(wrBuffer != NULL)
  260. {
  261. delete wrBuffer;
  262. wrBuffer = NULL;
  263. }
  264. if(syncMutex != NULL)
  265. {
  266. CloseHandle(syncMutex);
  267. syncMutex = NULL;
  268. }
  269. }
  270. };
  271. #endif