f_thor.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003
  1. /*
  2. * f_thor.c -- USB TIZEN THOR Downloader gadget function
  3. *
  4. * Copyright (C) 2013 Samsung Electronics
  5. * Lukasz Majewski <l.majewski@samsung.com>
  6. *
  7. * Based on code from:
  8. * git://review.tizen.org/kernel/u-boot
  9. *
  10. * Developed by:
  11. * Copyright (C) 2009 Samsung Electronics
  12. * Minkyu Kang <mk7.kang@samsung.com>
  13. * Sanghee Kim <sh0130.kim@samsung.com>
  14. *
  15. * SPDX-License-Identifier: GPL-2.0+
  16. */
  17. #include <errno.h>
  18. #include <common.h>
  19. #include <malloc.h>
  20. #include <version.h>
  21. #include <linux/usb/ch9.h>
  22. #include <linux/usb/gadget.h>
  23. #include <linux/usb/composite.h>
  24. #include <linux/usb/cdc.h>
  25. #include <g_dnl.h>
  26. #include <dfu.h>
  27. #include "f_thor.h"
  28. static void thor_tx_data(unsigned char *data, int len);
  29. static void thor_set_dma(void *addr, int len);
  30. static int thor_rx_data(void);
  31. static struct f_thor *thor_func;
  32. static inline struct f_thor *func_to_thor(struct usb_function *f)
  33. {
  34. return container_of(f, struct f_thor, usb_function);
  35. }
  36. DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_tx_data_buf,
  37. sizeof(struct rsp_box));
  38. DEFINE_CACHE_ALIGN_BUFFER(unsigned char, thor_rx_data_buf,
  39. sizeof(struct rqt_box));
  40. /* ********************************************************** */
  41. /* THOR protocol - transmission handling */
  42. /* ********************************************************** */
  43. DEFINE_CACHE_ALIGN_BUFFER(char, f_name, F_NAME_BUF_SIZE);
  44. static unsigned long long int thor_file_size;
  45. static int alt_setting_num;
  46. static void send_rsp(const struct rsp_box *rsp)
  47. {
  48. memcpy(thor_tx_data_buf, rsp, sizeof(struct rsp_box));
  49. thor_tx_data(thor_tx_data_buf, sizeof(struct rsp_box));
  50. debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
  51. }
  52. static void send_data_rsp(s32 ack, s32 count)
  53. {
  54. ALLOC_CACHE_ALIGN_BUFFER(struct data_rsp_box, rsp,
  55. sizeof(struct data_rsp_box));
  56. rsp->ack = ack;
  57. rsp->count = count;
  58. memcpy(thor_tx_data_buf, rsp, sizeof(struct data_rsp_box));
  59. thor_tx_data(thor_tx_data_buf, sizeof(struct data_rsp_box));
  60. debug("-DATA RSP: %d, %d\n", ack, count);
  61. }
  62. static int process_rqt_info(const struct rqt_box *rqt)
  63. {
  64. ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
  65. memset(rsp, 0, sizeof(struct rsp_box));
  66. rsp->rsp = rqt->rqt;
  67. rsp->rsp_data = rqt->rqt_data;
  68. switch (rqt->rqt_data) {
  69. case RQT_INFO_VER_PROTOCOL:
  70. rsp->int_data[0] = VER_PROTOCOL_MAJOR;
  71. rsp->int_data[1] = VER_PROTOCOL_MINOR;
  72. break;
  73. case RQT_INIT_VER_HW:
  74. snprintf(rsp->str_data[0], sizeof(rsp->str_data[0]),
  75. "%x", checkboard());
  76. break;
  77. case RQT_INIT_VER_BOOT:
  78. sprintf(rsp->str_data[0], "%s", U_BOOT_VERSION);
  79. break;
  80. case RQT_INIT_VER_KERNEL:
  81. sprintf(rsp->str_data[0], "%s", "k unknown");
  82. break;
  83. case RQT_INIT_VER_PLATFORM:
  84. sprintf(rsp->str_data[0], "%s", "p unknown");
  85. break;
  86. case RQT_INIT_VER_CSC:
  87. sprintf(rsp->str_data[0], "%s", "c unknown");
  88. break;
  89. default:
  90. return -EINVAL;
  91. }
  92. send_rsp(rsp);
  93. return true;
  94. }
  95. static int process_rqt_cmd(const struct rqt_box *rqt)
  96. {
  97. ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
  98. memset(rsp, 0, sizeof(struct rsp_box));
  99. rsp->rsp = rqt->rqt;
  100. rsp->rsp_data = rqt->rqt_data;
  101. switch (rqt->rqt_data) {
  102. case RQT_CMD_REBOOT:
  103. debug("TARGET RESET\n");
  104. send_rsp(rsp);
  105. g_dnl_unregister();
  106. dfu_free_entities();
  107. run_command("reset", 0);
  108. break;
  109. case RQT_CMD_POWEROFF:
  110. case RQT_CMD_EFSCLEAR:
  111. send_rsp(rsp);
  112. default:
  113. printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
  114. return -EINVAL;
  115. }
  116. return true;
  117. }
  118. static long long int download_head(unsigned long long total,
  119. unsigned int packet_size,
  120. long long int *left,
  121. int *cnt)
  122. {
  123. long long int rcv_cnt = 0, left_to_rcv, ret_rcv;
  124. void *transfer_buffer = dfu_get_buf();
  125. void *buf = transfer_buffer;
  126. int usb_pkt_cnt = 0, ret;
  127. /*
  128. * Files smaller than THOR_STORE_UNIT_SIZE (now 32 MiB) are stored on
  129. * the medium.
  130. * The packet response is sent on the purpose after successful data
  131. * chunk write. There is a room for improvement when asynchronous write
  132. * is performed.
  133. */
  134. while (total - rcv_cnt >= packet_size) {
  135. thor_set_dma(buf, packet_size);
  136. buf += packet_size;
  137. ret_rcv = thor_rx_data();
  138. if (ret_rcv < 0)
  139. return ret_rcv;
  140. rcv_cnt += ret_rcv;
  141. debug("%d: RCV data count: %llu cnt: %d\n", usb_pkt_cnt,
  142. rcv_cnt, *cnt);
  143. if ((rcv_cnt % THOR_STORE_UNIT_SIZE) == 0) {
  144. ret = dfu_write(dfu_get_entity(alt_setting_num),
  145. transfer_buffer, THOR_STORE_UNIT_SIZE,
  146. (*cnt)++);
  147. if (ret) {
  148. error("DFU write failed [%d] cnt: %d",
  149. ret, *cnt);
  150. return ret;
  151. }
  152. buf = transfer_buffer;
  153. }
  154. send_data_rsp(0, ++usb_pkt_cnt);
  155. }
  156. /* Calculate the amount of data to arrive from PC (in bytes) */
  157. left_to_rcv = total - rcv_cnt;
  158. /*
  159. * Calculate number of data already received. but not yet stored
  160. * on the medium (they are smaller than THOR_STORE_UNIT_SIZE)
  161. */
  162. *left = left_to_rcv + buf - transfer_buffer;
  163. debug("%s: left: %llu left_to_rcv: %llu buf: 0x%p\n", __func__,
  164. *left, left_to_rcv, buf);
  165. if (left_to_rcv) {
  166. thor_set_dma(buf, packet_size);
  167. ret_rcv = thor_rx_data();
  168. if (ret_rcv < 0)
  169. return ret_rcv;
  170. rcv_cnt += ret_rcv;
  171. send_data_rsp(0, ++usb_pkt_cnt);
  172. }
  173. debug("%s: %llu total: %llu cnt: %d\n", __func__, rcv_cnt, total, *cnt);
  174. return rcv_cnt;
  175. }
  176. static int download_tail(long long int left, int cnt)
  177. {
  178. void *transfer_buffer = dfu_get_buf();
  179. int ret;
  180. debug("%s: left: %llu cnt: %d\n", __func__, left, cnt);
  181. if (left) {
  182. ret = dfu_write(dfu_get_entity(alt_setting_num),
  183. transfer_buffer, left, cnt++);
  184. if (ret) {
  185. error("DFU write failed [%d]: left: %llu", ret, left);
  186. return ret;
  187. }
  188. }
  189. /*
  190. * To store last "packet" DFU storage backend requires dfu_write with
  191. * size parameter equal to 0
  192. *
  193. * This also frees memory malloc'ed by dfu_get_buf(), so no explicit
  194. * need fo call dfu_free_buf() is needed.
  195. */
  196. ret = dfu_write(dfu_get_entity(alt_setting_num),
  197. transfer_buffer, 0, cnt);
  198. if (ret)
  199. error("DFU write failed [%d] cnt: %d", ret, cnt);
  200. return ret;
  201. }
  202. static long long int process_rqt_download(const struct rqt_box *rqt)
  203. {
  204. ALLOC_CACHE_ALIGN_BUFFER(struct rsp_box, rsp, sizeof(struct rsp_box));
  205. static long long int left, ret_head;
  206. int file_type, ret = 0;
  207. static int cnt;
  208. memset(rsp, 0, sizeof(struct rsp_box));
  209. rsp->rsp = rqt->rqt;
  210. rsp->rsp_data = rqt->rqt_data;
  211. switch (rqt->rqt_data) {
  212. case RQT_DL_INIT:
  213. thor_file_size = rqt->int_data[0];
  214. debug("INIT: total %d bytes\n", rqt->int_data[0]);
  215. break;
  216. case RQT_DL_FILE_INFO:
  217. file_type = rqt->int_data[0];
  218. if (file_type == FILE_TYPE_PIT) {
  219. puts("PIT table file - not supported\n");
  220. rsp->ack = -ENOTSUPP;
  221. ret = rsp->ack;
  222. break;
  223. }
  224. thor_file_size = rqt->int_data[1];
  225. memcpy(f_name, rqt->str_data[0], F_NAME_BUF_SIZE);
  226. debug("INFO: name(%s, %d), size(%llu), type(%d)\n",
  227. f_name, 0, thor_file_size, file_type);
  228. rsp->int_data[0] = THOR_PACKET_SIZE;
  229. alt_setting_num = dfu_get_alt(f_name);
  230. if (alt_setting_num < 0) {
  231. error("Alt setting [%d] to write not found!",
  232. alt_setting_num);
  233. rsp->ack = -ENODEV;
  234. ret = rsp->ack;
  235. }
  236. break;
  237. case RQT_DL_FILE_START:
  238. send_rsp(rsp);
  239. ret_head = download_head(thor_file_size, THOR_PACKET_SIZE,
  240. &left, &cnt);
  241. if (ret_head < 0) {
  242. left = 0;
  243. cnt = 0;
  244. }
  245. return ret_head;
  246. case RQT_DL_FILE_END:
  247. debug("DL FILE_END\n");
  248. rsp->ack = download_tail(left, cnt);
  249. ret = rsp->ack;
  250. left = 0;
  251. cnt = 0;
  252. break;
  253. case RQT_DL_EXIT:
  254. debug("DL EXIT\n");
  255. break;
  256. default:
  257. error("Operation not supported: %d", rqt->rqt_data);
  258. ret = -ENOTSUPP;
  259. }
  260. send_rsp(rsp);
  261. return ret;
  262. }
  263. static int process_data(void)
  264. {
  265. ALLOC_CACHE_ALIGN_BUFFER(struct rqt_box, rqt, sizeof(struct rqt_box));
  266. int ret = -EINVAL;
  267. memset(rqt, 0, sizeof(rqt));
  268. memcpy(rqt, thor_rx_data_buf, sizeof(struct rqt_box));
  269. debug("+RQT: %d, %d\n", rqt->rqt, rqt->rqt_data);
  270. switch (rqt->rqt) {
  271. case RQT_INFO:
  272. ret = process_rqt_info(rqt);
  273. break;
  274. case RQT_CMD:
  275. ret = process_rqt_cmd(rqt);
  276. break;
  277. case RQT_DL:
  278. ret = (int) process_rqt_download(rqt);
  279. break;
  280. case RQT_UL:
  281. puts("RQT: UPLOAD not supported!\n");
  282. break;
  283. default:
  284. error("unknown request (%d)", rqt->rqt);
  285. }
  286. return ret;
  287. }
  288. /* ********************************************************** */
  289. /* THOR USB Function */
  290. /* ********************************************************** */
  291. static inline struct usb_endpoint_descriptor *
  292. ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *hs,
  293. struct usb_endpoint_descriptor *fs)
  294. {
  295. if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
  296. return hs;
  297. return fs;
  298. }
  299. static struct usb_interface_descriptor thor_downloader_intf_data = {
  300. .bLength = sizeof(thor_downloader_intf_data),
  301. .bDescriptorType = USB_DT_INTERFACE,
  302. .bNumEndpoints = 2,
  303. .bInterfaceClass = USB_CLASS_CDC_DATA,
  304. };
  305. static struct usb_endpoint_descriptor fs_in_desc = {
  306. .bLength = USB_DT_ENDPOINT_SIZE,
  307. .bDescriptorType = USB_DT_ENDPOINT,
  308. .bEndpointAddress = USB_DIR_IN,
  309. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  310. };
  311. static struct usb_endpoint_descriptor fs_out_desc = {
  312. .bLength = USB_DT_ENDPOINT_SIZE,
  313. .bDescriptorType = USB_DT_ENDPOINT,
  314. .bEndpointAddress = USB_DIR_OUT,
  315. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  316. };
  317. /* CDC configuration */
  318. static struct usb_interface_descriptor thor_downloader_intf_int = {
  319. .bLength = sizeof(thor_downloader_intf_int),
  320. .bDescriptorType = USB_DT_INTERFACE,
  321. .bNumEndpoints = 1,
  322. .bInterfaceClass = USB_CLASS_COMM,
  323. /* 0x02 Abstract Line Control Model */
  324. .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM,
  325. /* 0x01 Common AT commands */
  326. .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER,
  327. };
  328. static struct usb_cdc_header_desc thor_downloader_cdc_header = {
  329. .bLength = sizeof(thor_downloader_cdc_header),
  330. .bDescriptorType = 0x24, /* CS_INTERFACE */
  331. .bDescriptorSubType = 0x00,
  332. .bcdCDC = 0x0110,
  333. };
  334. static struct usb_cdc_call_mgmt_descriptor thor_downloader_cdc_call = {
  335. .bLength = sizeof(thor_downloader_cdc_call),
  336. .bDescriptorType = 0x24, /* CS_INTERFACE */
  337. .bDescriptorSubType = 0x01,
  338. .bmCapabilities = 0x00,
  339. .bDataInterface = 0x01,
  340. };
  341. static struct usb_cdc_acm_descriptor thor_downloader_cdc_abstract = {
  342. .bLength = sizeof(thor_downloader_cdc_abstract),
  343. .bDescriptorType = 0x24, /* CS_INTERFACE */
  344. .bDescriptorSubType = 0x02,
  345. .bmCapabilities = 0x00,
  346. };
  347. static struct usb_cdc_union_desc thor_downloader_cdc_union = {
  348. .bLength = sizeof(thor_downloader_cdc_union),
  349. .bDescriptorType = 0x24, /* CS_INTERFACE */
  350. .bDescriptorSubType = USB_CDC_UNION_TYPE,
  351. };
  352. static struct usb_endpoint_descriptor fs_int_desc = {
  353. .bLength = USB_DT_ENDPOINT_SIZE,
  354. .bDescriptorType = USB_DT_ENDPOINT,
  355. .bEndpointAddress = 3 | USB_DIR_IN,
  356. .bmAttributes = USB_ENDPOINT_XFER_INT,
  357. .wMaxPacketSize = __constant_cpu_to_le16(16),
  358. .bInterval = 0x9,
  359. };
  360. static struct usb_interface_assoc_descriptor
  361. thor_iad_descriptor = {
  362. .bLength = sizeof(thor_iad_descriptor),
  363. .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION,
  364. .bFirstInterface = 0,
  365. .bInterfaceCount = 2, /* control + data */
  366. .bFunctionClass = USB_CLASS_COMM,
  367. .bFunctionSubClass = USB_CDC_SUBCLASS_ACM,
  368. .bFunctionProtocol = USB_CDC_PROTO_NONE,
  369. };
  370. static struct usb_endpoint_descriptor hs_in_desc = {
  371. .bLength = USB_DT_ENDPOINT_SIZE,
  372. .bDescriptorType = USB_DT_ENDPOINT,
  373. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  374. .wMaxPacketSize = __constant_cpu_to_le16(512),
  375. };
  376. static struct usb_endpoint_descriptor hs_out_desc = {
  377. .bLength = USB_DT_ENDPOINT_SIZE,
  378. .bDescriptorType = USB_DT_ENDPOINT,
  379. .bmAttributes = USB_ENDPOINT_XFER_BULK,
  380. .wMaxPacketSize = __constant_cpu_to_le16(512),
  381. };
  382. static struct usb_endpoint_descriptor hs_int_desc = {
  383. .bLength = USB_DT_ENDPOINT_SIZE,
  384. .bDescriptorType = USB_DT_ENDPOINT,
  385. .bmAttributes = USB_ENDPOINT_XFER_INT,
  386. .wMaxPacketSize = __constant_cpu_to_le16(16),
  387. .bInterval = 0x9,
  388. };
  389. static struct usb_qualifier_descriptor dev_qualifier = {
  390. .bLength = sizeof(dev_qualifier),
  391. .bDescriptorType = USB_DT_DEVICE_QUALIFIER,
  392. .bcdUSB = __constant_cpu_to_le16(0x0200),
  393. .bDeviceClass = USB_CLASS_VENDOR_SPEC,
  394. .bNumConfigurations = 2,
  395. };
  396. /*
  397. * This attribute vendor descriptor is necessary for correct operation with
  398. * Windows version of THOR download program
  399. *
  400. * It prevents windows driver from sending zero lenght packet (ZLP) after
  401. * each THOR_PACKET_SIZE. This assures consistent behaviour with libusb
  402. */
  403. static struct usb_cdc_attribute_vendor_descriptor thor_downloader_cdc_av = {
  404. .bLength = sizeof(thor_downloader_cdc_av),
  405. .bDescriptorType = 0x24,
  406. .bDescriptorSubType = 0x80,
  407. .DAUType = 0x0002,
  408. .DAULength = 0x0001,
  409. .DAUValue = 0x00,
  410. };
  411. static const struct usb_descriptor_header *hs_thor_downloader_function[] = {
  412. (struct usb_descriptor_header *)&thor_iad_descriptor,
  413. (struct usb_descriptor_header *)&thor_downloader_intf_int,
  414. (struct usb_descriptor_header *)&thor_downloader_cdc_header,
  415. (struct usb_descriptor_header *)&thor_downloader_cdc_call,
  416. (struct usb_descriptor_header *)&thor_downloader_cdc_abstract,
  417. (struct usb_descriptor_header *)&thor_downloader_cdc_union,
  418. (struct usb_descriptor_header *)&hs_int_desc,
  419. (struct usb_descriptor_header *)&thor_downloader_intf_data,
  420. (struct usb_descriptor_header *)&thor_downloader_cdc_av,
  421. (struct usb_descriptor_header *)&hs_in_desc,
  422. (struct usb_descriptor_header *)&hs_out_desc,
  423. NULL,
  424. };
  425. /*-------------------------------------------------------------------------*/
  426. static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
  427. {
  428. struct usb_request *req;
  429. req = usb_ep_alloc_request(ep, 0);
  430. if (!req)
  431. return req;
  432. req->length = length;
  433. req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
  434. if (!req->buf) {
  435. usb_ep_free_request(ep, req);
  436. req = NULL;
  437. }
  438. return req;
  439. }
  440. static int thor_rx_data(void)
  441. {
  442. struct thor_dev *dev = thor_func->dev;
  443. int data_to_rx, tmp, status;
  444. data_to_rx = dev->out_req->length;
  445. tmp = data_to_rx;
  446. do {
  447. dev->out_req->length = data_to_rx;
  448. debug("dev->out_req->length:%d dev->rxdata:%d\n",
  449. dev->out_req->length, dev->rxdata);
  450. status = usb_ep_queue(dev->out_ep, dev->out_req, 0);
  451. if (status) {
  452. error("kill %s: resubmit %d bytes --> %d",
  453. dev->out_ep->name, dev->out_req->length, status);
  454. usb_ep_set_halt(dev->out_ep);
  455. return -EAGAIN;
  456. }
  457. while (!dev->rxdata) {
  458. usb_gadget_handle_interrupts();
  459. if (ctrlc())
  460. return -1;
  461. }
  462. dev->rxdata = 0;
  463. data_to_rx -= dev->out_req->actual;
  464. } while (data_to_rx);
  465. return tmp;
  466. }
  467. static void thor_tx_data(unsigned char *data, int len)
  468. {
  469. struct thor_dev *dev = thor_func->dev;
  470. unsigned char *ptr = dev->in_req->buf;
  471. int status;
  472. memset(ptr, 0, len);
  473. memcpy(ptr, data, len);
  474. dev->in_req->length = len;
  475. debug("%s: dev->in_req->length:%d to_cpy:%d\n", __func__,
  476. dev->in_req->length, sizeof(data));
  477. status = usb_ep_queue(dev->in_ep, dev->in_req, 0);
  478. if (status) {
  479. error("kill %s: resubmit %d bytes --> %d",
  480. dev->in_ep->name, dev->in_req->length, status);
  481. usb_ep_set_halt(dev->in_ep);
  482. }
  483. /* Wait until tx interrupt received */
  484. while (!dev->txdata)
  485. usb_gadget_handle_interrupts();
  486. dev->txdata = 0;
  487. }
  488. static void thor_rx_tx_complete(struct usb_ep *ep, struct usb_request *req)
  489. {
  490. struct thor_dev *dev = thor_func->dev;
  491. int status = req->status;
  492. debug("%s: ep_ptr:%p, req_ptr:%p\n", __func__, ep, req);
  493. switch (status) {
  494. case 0:
  495. if (ep == dev->out_ep)
  496. dev->rxdata = 1;
  497. else
  498. dev->txdata = 1;
  499. break;
  500. /* this endpoint is normally active while we're configured */
  501. case -ECONNABORTED: /* hardware forced ep reset */
  502. case -ECONNRESET: /* request dequeued */
  503. case -ESHUTDOWN: /* disconnect from host */
  504. case -EREMOTEIO: /* short read */
  505. case -EOVERFLOW:
  506. error("ERROR:%d", status);
  507. break;
  508. }
  509. debug("%s complete --> %d, %d/%d\n", ep->name,
  510. status, req->actual, req->length);
  511. }
  512. static struct usb_request *thor_start_ep(struct usb_ep *ep)
  513. {
  514. struct usb_request *req;
  515. req = alloc_ep_req(ep, THOR_PACKET_SIZE);
  516. debug("%s: ep:%p req:%p\n", __func__, ep, req);
  517. if (!req)
  518. return NULL;
  519. memset(req->buf, 0, req->length);
  520. req->complete = thor_rx_tx_complete;
  521. memset(req->buf, 0x55, req->length);
  522. return req;
  523. }
  524. static void thor_setup_complete(struct usb_ep *ep, struct usb_request *req)
  525. {
  526. if (req->status || req->actual != req->length)
  527. debug("setup complete --> %d, %d/%d\n",
  528. req->status, req->actual, req->length);
  529. }
  530. static int
  531. thor_func_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
  532. {
  533. struct thor_dev *dev = thor_func->dev;
  534. struct usb_request *req = dev->req;
  535. struct usb_gadget *gadget = dev->gadget;
  536. int value = 0;
  537. u16 len = le16_to_cpu(ctrl->wLength);
  538. debug("Req_Type: 0x%x Req: 0x%x wValue: 0x%x wIndex: 0x%x wLen: 0x%x\n",
  539. ctrl->bRequestType, ctrl->bRequest, ctrl->wValue, ctrl->wIndex,
  540. ctrl->wLength);
  541. switch (ctrl->bRequest) {
  542. case USB_CDC_REQ_SET_CONTROL_LINE_STATE:
  543. value = 0;
  544. break;
  545. case USB_CDC_REQ_SET_LINE_CODING:
  546. value = len;
  547. /* Line Coding set done = configuration done */
  548. thor_func->dev->configuration_done = 1;
  549. break;
  550. default:
  551. error("thor_setup: unknown request: %d", ctrl->bRequest);
  552. }
  553. if (value >= 0) {
  554. req->length = value;
  555. req->zero = value < len;
  556. value = usb_ep_queue(gadget->ep0, req, 0);
  557. if (value < 0) {
  558. debug("%s: ep_queue: %d\n", __func__, value);
  559. req->status = 0;
  560. }
  561. }
  562. return value;
  563. }
  564. /* Specific to the THOR protocol */
  565. static void thor_set_dma(void *addr, int len)
  566. {
  567. struct thor_dev *dev = thor_func->dev;
  568. debug("in_req:%p, out_req:%p\n", dev->in_req, dev->out_req);
  569. debug("addr:%p, len:%d\n", addr, len);
  570. dev->out_req->buf = addr;
  571. dev->out_req->length = len;
  572. }
  573. int thor_init(void)
  574. {
  575. struct thor_dev *dev = thor_func->dev;
  576. /* Wait for a device enumeration and configuration settings */
  577. debug("THOR enumeration/configuration setting....\n");
  578. while (!dev->configuration_done)
  579. usb_gadget_handle_interrupts();
  580. thor_set_dma(thor_rx_data_buf, strlen("THOR"));
  581. /* detect the download request from Host PC */
  582. if (thor_rx_data() < 0) {
  583. printf("%s: Data not received!\n", __func__);
  584. return -1;
  585. }
  586. if (!strncmp((char *)thor_rx_data_buf, "THOR", strlen("THOR"))) {
  587. puts("Download request from the Host PC\n");
  588. udelay(30 * 1000); /* 30 ms */
  589. strcpy((char *)thor_tx_data_buf, "ROHT");
  590. thor_tx_data(thor_tx_data_buf, strlen("ROHT"));
  591. } else {
  592. puts("Wrong reply information\n");
  593. return -1;
  594. }
  595. return 0;
  596. }
  597. int thor_handle(void)
  598. {
  599. int ret;
  600. /* receive the data from Host PC */
  601. while (1) {
  602. thor_set_dma(thor_rx_data_buf, sizeof(struct rqt_box));
  603. ret = thor_rx_data();
  604. if (ret > 0) {
  605. ret = process_data();
  606. if (ret < 0)
  607. return ret;
  608. } else {
  609. printf("%s: No data received!\n", __func__);
  610. break;
  611. }
  612. }
  613. return 0;
  614. }
  615. static int thor_func_bind(struct usb_configuration *c, struct usb_function *f)
  616. {
  617. struct usb_gadget *gadget = c->cdev->gadget;
  618. struct f_thor *f_thor = func_to_thor(f);
  619. struct thor_dev *dev;
  620. struct usb_ep *ep;
  621. int status;
  622. thor_func = f_thor;
  623. dev = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*dev));
  624. if (!dev)
  625. return -ENOMEM;
  626. memset(dev, 0, sizeof(*dev));
  627. dev->gadget = gadget;
  628. f_thor->dev = dev;
  629. debug("%s: usb_configuration: 0x%p usb_function: 0x%p\n",
  630. __func__, c, f);
  631. debug("f_thor: 0x%p thor: 0x%p\n", f_thor, dev);
  632. /* EP0 */
  633. /* preallocate control response and buffer */
  634. dev->req = usb_ep_alloc_request(gadget->ep0, 0);
  635. if (!dev->req) {
  636. status = -ENOMEM;
  637. goto fail;
  638. }
  639. dev->req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE,
  640. gadget->ep0->maxpacket);
  641. if (!dev->req->buf) {
  642. status = -ENOMEM;
  643. goto fail;
  644. }
  645. dev->req->complete = thor_setup_complete;
  646. /* DYNAMIC interface numbers assignments */
  647. status = usb_interface_id(c, f);
  648. if (status < 0)
  649. goto fail;
  650. thor_downloader_intf_int.bInterfaceNumber = status;
  651. thor_downloader_cdc_union.bMasterInterface0 = status;
  652. status = usb_interface_id(c, f);
  653. if (status < 0)
  654. goto fail;
  655. thor_downloader_intf_data.bInterfaceNumber = status;
  656. thor_downloader_cdc_union.bSlaveInterface0 = status;
  657. /* allocate instance-specific endpoints */
  658. ep = usb_ep_autoconfig(gadget, &fs_in_desc);
  659. if (!ep) {
  660. status = -ENODEV;
  661. goto fail;
  662. }
  663. if (gadget_is_dualspeed(gadget)) {
  664. hs_in_desc.bEndpointAddress =
  665. fs_in_desc.bEndpointAddress;
  666. }
  667. dev->in_ep = ep; /* Store IN EP for enabling @ setup */
  668. ep = usb_ep_autoconfig(gadget, &fs_out_desc);
  669. if (!ep) {
  670. status = -ENODEV;
  671. goto fail;
  672. }
  673. if (gadget_is_dualspeed(gadget))
  674. hs_out_desc.bEndpointAddress =
  675. fs_out_desc.bEndpointAddress;
  676. dev->out_ep = ep; /* Store OUT EP for enabling @ setup */
  677. ep = usb_ep_autoconfig(gadget, &fs_int_desc);
  678. if (!ep) {
  679. status = -ENODEV;
  680. goto fail;
  681. }
  682. dev->int_ep = ep;
  683. if (gadget_is_dualspeed(gadget)) {
  684. hs_int_desc.bEndpointAddress =
  685. fs_int_desc.bEndpointAddress;
  686. f->hs_descriptors = (struct usb_descriptor_header **)
  687. &hs_thor_downloader_function;
  688. if (!f->hs_descriptors)
  689. goto fail;
  690. }
  691. debug("%s: out_ep:%p out_req:%p\n", __func__,
  692. dev->out_ep, dev->out_req);
  693. return 0;
  694. fail:
  695. free(dev);
  696. return status;
  697. }
  698. static void free_ep_req(struct usb_ep *ep, struct usb_request *req)
  699. {
  700. free(req->buf);
  701. usb_ep_free_request(ep, req);
  702. }
  703. static void thor_unbind(struct usb_configuration *c, struct usb_function *f)
  704. {
  705. struct f_thor *f_thor = func_to_thor(f);
  706. struct thor_dev *dev = f_thor->dev;
  707. free(dev);
  708. memset(thor_func, 0, sizeof(*thor_func));
  709. thor_func = NULL;
  710. }
  711. static void thor_func_disable(struct usb_function *f)
  712. {
  713. struct f_thor *f_thor = func_to_thor(f);
  714. struct thor_dev *dev = f_thor->dev;
  715. debug("%s:\n", __func__);
  716. /* Avoid freeing memory when ep is still claimed */
  717. if (dev->in_ep->driver_data) {
  718. free_ep_req(dev->in_ep, dev->in_req);
  719. usb_ep_disable(dev->in_ep);
  720. dev->in_ep->driver_data = NULL;
  721. }
  722. if (dev->out_ep->driver_data) {
  723. dev->out_req->buf = NULL;
  724. usb_ep_free_request(dev->out_ep, dev->out_req);
  725. usb_ep_disable(dev->out_ep);
  726. dev->out_ep->driver_data = NULL;
  727. }
  728. if (dev->int_ep->driver_data) {
  729. usb_ep_disable(dev->int_ep);
  730. dev->int_ep->driver_data = NULL;
  731. }
  732. }
  733. static int thor_eps_setup(struct usb_function *f)
  734. {
  735. struct usb_composite_dev *cdev = f->config->cdev;
  736. struct usb_gadget *gadget = cdev->gadget;
  737. struct thor_dev *dev = thor_func->dev;
  738. struct usb_endpoint_descriptor *d;
  739. struct usb_request *req;
  740. struct usb_ep *ep;
  741. int result;
  742. ep = dev->in_ep;
  743. d = ep_desc(gadget, &hs_in_desc, &fs_in_desc);
  744. debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
  745. result = usb_ep_enable(ep, d);
  746. if (result)
  747. goto exit;
  748. ep->driver_data = cdev; /* claim */
  749. req = thor_start_ep(ep);
  750. if (!req) {
  751. usb_ep_disable(ep);
  752. result = -EIO;
  753. goto exit;
  754. }
  755. dev->in_req = req;
  756. ep = dev->out_ep;
  757. d = ep_desc(gadget, &hs_out_desc, &fs_out_desc);
  758. debug("(d)bEndpointAddress: 0x%x\n", d->bEndpointAddress);
  759. result = usb_ep_enable(ep, d);
  760. if (result)
  761. goto exit;
  762. ep->driver_data = cdev; /* claim */
  763. req = thor_start_ep(ep);
  764. if (!req) {
  765. usb_ep_disable(ep);
  766. result = -EIO;
  767. goto exit;
  768. }
  769. dev->out_req = req;
  770. /* ACM control EP */
  771. ep = dev->int_ep;
  772. ep->driver_data = cdev; /* claim */
  773. exit:
  774. return result;
  775. }
  776. static int thor_func_set_alt(struct usb_function *f,
  777. unsigned intf, unsigned alt)
  778. {
  779. struct thor_dev *dev = thor_func->dev;
  780. int result;
  781. debug("%s: func: %s intf: %d alt: %d\n",
  782. __func__, f->name, intf, alt);
  783. switch (intf) {
  784. case 0:
  785. debug("ACM INTR interface\n");
  786. break;
  787. case 1:
  788. debug("Communication Data interface\n");
  789. result = thor_eps_setup(f);
  790. if (result)
  791. error("%s: EPs setup failed!", __func__);
  792. dev->configuration_done = 1;
  793. break;
  794. }
  795. return 0;
  796. }
  797. static int thor_func_init(struct usb_configuration *c)
  798. {
  799. struct f_thor *f_thor;
  800. int status;
  801. debug("%s: cdev: 0x%p\n", __func__, c->cdev);
  802. f_thor = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_thor));
  803. if (!f_thor)
  804. return -ENOMEM;
  805. memset(f_thor, 0, sizeof(*f_thor));
  806. f_thor->usb_function.name = "f_thor";
  807. f_thor->usb_function.bind = thor_func_bind;
  808. f_thor->usb_function.unbind = thor_unbind;
  809. f_thor->usb_function.setup = thor_func_setup;
  810. f_thor->usb_function.set_alt = thor_func_set_alt;
  811. f_thor->usb_function.disable = thor_func_disable;
  812. status = usb_add_function(c, &f_thor->usb_function);
  813. if (status)
  814. free(f_thor);
  815. return status;
  816. }
  817. int thor_add(struct usb_configuration *c)
  818. {
  819. debug("%s:\n", __func__);
  820. return thor_func_init(c);
  821. }