PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/xpp/pic_loader.c

https://github.com/brycied00d/dahdi-tools
C | 285 lines | 238 code | 17 blank | 30 comment | 51 complexity | 6b9d3e18d51a74dc3c2c3158e56f9ff8 MD5 | raw file
  1. /*
  2. * Written by Oron Peled <oron@actcom.co.il>
  3. * Copyright (C) 2008, Xorcom
  4. *
  5. * All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. *
  21. */
  22. #include <assert.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <errno.h>
  26. #include <regex.h>
  27. #include "hexfile.h"
  28. #include "pic_loader.h"
  29. #include <debug.h>
  30. #include <xusb.h>
  31. #define DBG_MASK 0x03
  32. #define MAX_HEX_LINES 10000
  33. #define TIMEOUT 500
  34. enum xpp_packet_types {
  35. PIC_REQ_XOP = 0x09,
  36. PIC_REP_XOP = 0x0A
  37. };
  38. struct xpp_packet_header {
  39. struct {
  40. uint16_t len;
  41. uint8_t op;
  42. uint8_t unit;
  43. } PACKED header;
  44. union {
  45. struct {
  46. struct {
  47. uint8_t flags;
  48. uint8_t card_type;
  49. uint16_t offs;
  50. } pic_header;
  51. uint8_t data[3];
  52. } PACKED pic_packet;
  53. } d;
  54. } PACKED;
  55. int send_picline(struct astribank_device *astribank, uint8_t card_type, enum pic_command pcmd, int offs, uint8_t *data, int data_len)
  56. {
  57. int recv_answer = 0;
  58. char buf[PACKET_SIZE];
  59. struct xpp_packet_header *phead = (struct xpp_packet_header *)buf;
  60. int pack_len;
  61. int ret;
  62. assert(astribank != NULL);
  63. pack_len = data_len + sizeof(phead->header) + sizeof(phead->d.pic_packet.pic_header);
  64. phead->header.len = pack_len;
  65. phead->header.op = PIC_REQ_XOP;
  66. phead->header.unit = 0x00;
  67. phead->d.pic_packet.pic_header.flags = pcmd;
  68. phead->d.pic_packet.pic_header.card_type = card_type;
  69. phead->d.pic_packet.pic_header.offs = offs;
  70. if(data)
  71. memcpy(phead->d.pic_packet.data, data, data_len);
  72. switch (pcmd) {
  73. case PIC_START_FLAG:
  74. break;
  75. case PIC_DATA_FLAG:
  76. break;
  77. case PIC_END_FLAG:
  78. recv_answer = 1;
  79. break;
  80. case PIC_ENDS_FLAG:
  81. break;
  82. }
  83. DBG("PICLINE: pack_len=%d pcmd=%d\n", pack_len, pcmd);
  84. dump_packet(LOG_DEBUG, DBG_MASK, "dump:picline[W]", (char *)phead, pack_len);
  85. ret = xusb_send(astribank->xusb, buf, pack_len, TIMEOUT);
  86. if(ret < 0) {
  87. ERR("xusb_send failed: %d\n", ret);
  88. return ret;
  89. }
  90. DBG("xusb_send: Written %d bytes\n", ret);
  91. if (recv_answer) {
  92. ret = xusb_recv(astribank->xusb, buf, sizeof(buf), TIMEOUT);
  93. if(ret <= 0) {
  94. ERR("No USB packs to read\n");
  95. return ret;
  96. } else {
  97. phead = (struct xpp_packet_header *)buf;
  98. if(phead->header.op != PIC_REP_XOP) {
  99. ERR("Got unexpected reply OP=0x%02X\n", phead->header.op);
  100. dump_packet(LOG_ERR, DBG_MASK, "hexline[ERR]", buf, ret);
  101. return -EINVAL;
  102. }
  103. DBG("received OP=0x%02X, checksum=%02X\n", phead->header.op, phead->d.pic_packet.data[0]);
  104. if(phead->d.pic_packet.data[0] != 0) {
  105. ERR("PIC burning, bad checksum\n");
  106. return -EINVAL;
  107. }
  108. }
  109. }
  110. return 0;
  111. }
  112. static const char *pic_basename(const char *fname, uint8_t *card_type)
  113. {
  114. const char *basename;
  115. regex_t regex;
  116. char ebuf[BUFSIZ];
  117. const char re[] = "PIC_TYPE_([0-9]+)\\.hex";
  118. regmatch_t pmatch[2]; /* One for the whole match, one for the number */
  119. int nmatch = (sizeof(pmatch)/sizeof(pmatch[0]));
  120. int len;
  121. int ret;
  122. basename = strrchr(fname, '/');
  123. if(!basename)
  124. basename = fname;
  125. if((ret = regcomp(&regex, re, REG_ICASE | REG_EXTENDED)) != 0) {
  126. regerror(ret, &regex, ebuf, sizeof(ebuf));
  127. ERR("regcomp: %s\n", ebuf);
  128. return NULL;
  129. }
  130. if((ret = regexec(&regex, basename, nmatch, pmatch, 0)) != 0) {
  131. regerror(ret, &regex, ebuf, sizeof(ebuf));
  132. ERR("regexec: %s\n", ebuf);
  133. regfree(&regex);
  134. return NULL;
  135. }
  136. /*
  137. * Should have both complete match and a parentheses match
  138. */
  139. if(pmatch[0].rm_so == -1 || pmatch[1].rm_so == -1) {
  140. ERR("pic_basename: Bad match: pmatch[0].rm_so=%d pmatch[1].rm_so=%d\n",
  141. pmatch[0].rm_so, pmatch[1].rm_so == -1);
  142. regfree(&regex);
  143. return NULL;
  144. }
  145. len = pmatch[1].rm_eo - pmatch[1].rm_so;
  146. if(len >= sizeof(ebuf) - 1)
  147. len = sizeof(ebuf) - 1;
  148. memcpy(ebuf, basename + pmatch[1].rm_so, len);
  149. ebuf[len] = '\0';
  150. DBG("match: %s\n", ebuf);
  151. ret = atoi(ebuf);
  152. if(ret <= 0 || ret > 9) {
  153. ERR("pic_basename: Bad type number %d\n", ret);
  154. regfree(&regex);
  155. return NULL;
  156. }
  157. *card_type = ret;
  158. regfree(&regex);
  159. return basename;
  160. }
  161. /*
  162. * Returns: true on success, false on failure
  163. */
  164. static int pic_burn(struct astribank_device *astribank, const struct hexdata *hexdata)
  165. {
  166. const char *v = hexdata->version_info;
  167. const char *basename;
  168. uint8_t *data;
  169. unsigned char check_sum = 0;
  170. uint8_t card_type;
  171. int ret;
  172. unsigned int i;
  173. const char *devstr;
  174. v = (v[0]) ? v : "Unknown";
  175. assert(astribank != NULL);
  176. assert(hexdata != NULL);
  177. devstr = xusb_devpath(astribank->xusb);
  178. if(!astribank->is_usb2) {
  179. ERR("%s: Skip PIC burning (not USB2)\n", devstr);
  180. return 0;
  181. }
  182. INFO("%s [%s]: Loading PIC Firmware: %s (version %s)\n",
  183. devstr,
  184. xusb_serial(astribank->xusb),
  185. hexdata->fname,
  186. hexdata->version_info);
  187. basename = pic_basename(hexdata->fname, &card_type);
  188. if(!basename) {
  189. ERR("%s: Bad PIC filename '%s'. Abort.\n", devstr, hexdata->fname);
  190. return 0;
  191. }
  192. DBG("basename=%s card_type=%d maxlines=%d\n",
  193. basename, card_type, hexdata->maxlines);
  194. /*
  195. * Try to read extra left-overs from USB controller
  196. */
  197. for(i = 2; i; i--) {
  198. char buf[PACKET_SIZE];
  199. if(xusb_recv(astribank->xusb, buf, sizeof(buf), 1) <= 0)
  200. break;
  201. }
  202. if((ret = send_picline(astribank, card_type, PIC_START_FLAG, 0, NULL, 0)) != 0) {
  203. perror("Failed sending start hexline");
  204. return 0;
  205. }
  206. for(i = 0; i < hexdata->maxlines; i++) {
  207. struct hexline *hexline;
  208. unsigned int len;
  209. hexline = hexdata->lines[i];
  210. if(!hexline) {
  211. ERR("%s: hexdata finished early (line %d)", devstr, i);
  212. return 0;
  213. }
  214. if(hexline->d.content.header.tt == TT_DATA) {
  215. len = hexline->d.content.header.ll; /* don't send checksum */
  216. if(len != 3) {
  217. ERR("%s: Bad line len %d\n", devstr, len);
  218. return 0;
  219. }
  220. data = hexline->d.content.tt_data.data;
  221. check_sum ^= data[0] ^ data[1] ^ data[2];
  222. ret = send_picline(astribank, card_type, PIC_DATA_FLAG,
  223. hexline->d.content.header.offset, data, len);
  224. if(ret) {
  225. perror("Failed sending data hexline");
  226. return 0;
  227. }
  228. } else if(hexline->d.content.header.tt == TT_EOF) {
  229. break;
  230. } else {
  231. ERR("%s: Unexpected TT = %d in line %d\n",
  232. devstr, hexline->d.content.header.tt, i);
  233. return 0;
  234. }
  235. }
  236. if((ret = send_picline(astribank, card_type, PIC_END_FLAG, 0, &check_sum, 1)) != 0) {
  237. perror("Failed sending end hexline");
  238. return 0;
  239. }
  240. DBG("Finished...\n");
  241. return 1;
  242. }
  243. int load_pic(struct astribank_device *astribank, int numfiles, char *filelist[])
  244. {
  245. int i;
  246. const char *devstr;
  247. devstr = xusb_devpath(astribank->xusb);
  248. DBG("%s: Loading %d PIC files...\n", devstr, numfiles);
  249. for(i = 0; i < numfiles; i++) {
  250. struct hexdata *picdata;
  251. const char *curr = filelist[i];
  252. DBG("%s\n", curr);
  253. if((picdata = parse_hexfile(curr, MAX_HEX_LINES)) == NULL) {
  254. perror(curr);
  255. return -errno;
  256. }
  257. if(!pic_burn(astribank, picdata)) {
  258. ERR("%s: PIC %s burning failed\n", devstr, curr);
  259. return -ENODEV;
  260. }
  261. free_hexdata(picdata);
  262. }
  263. if((i = send_picline(astribank, 0, PIC_ENDS_FLAG, 0, NULL, 0)) != 0) {
  264. ERR("%s: PIC end burning failed\n", devstr);
  265. return -ENODEV;
  266. }
  267. return 0;
  268. }