dfeeb2b11b7105b9fa8d66dc48e0b6ee16068cac
[fw/stlink] / stm32l / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <time.h>
6 #include <sys/types.h>
7 #include <libusb-1.0/libusb.h>
8 #include "stlink-hw.h"
9
10 /* endianess related */
11 static inline unsigned int is_bigendian(void)
12 {
13   static volatile const unsigned int i = 1;
14   return *(volatile const char*) &i == 0;
15 }
16
17 static void write_uint32(unsigned char* buf, uint32_t ui)
18 {
19   if (!is_bigendian()) { // le -> le (don't swap)
20     buf[0] = ((unsigned char*) &ui)[0];
21     buf[1] = ((unsigned char*) &ui)[1];
22     buf[2] = ((unsigned char*) &ui)[2];
23     buf[3] = ((unsigned char*) &ui)[3];
24   } else {
25     buf[0] = ((unsigned char*) &ui)[3];
26     buf[1] = ((unsigned char*) &ui)[2];
27     buf[2] = ((unsigned char*) &ui)[1];
28     buf[3] = ((unsigned char*) &ui)[0];
29   }
30 }
31
32 static void write_uint16(unsigned char* buf, uint16_t ui)
33 {
34   if (!is_bigendian()) { // le -> le (don't swap)
35     buf[0] = ((unsigned char*) &ui)[0];
36     buf[1] = ((unsigned char*) &ui)[1];
37   } else {
38     buf[0] = ((unsigned char*) &ui)[1];
39     buf[1] = ((unsigned char*) &ui)[0];
40   }
41 }
42
43 static uint32_t read_uint32(const unsigned char *c, const int pt)
44 {
45   uint32_t ui;
46   char *p = (char *) &ui;
47
48   if (!is_bigendian()) { // le -> le (don't swap)
49     p[0] = c[pt];
50     p[1] = c[pt + 1];
51     p[2] = c[pt + 2];
52     p[3] = c[pt + 3];
53   } else {
54     p[0] = c[pt + 3];
55     p[1] = c[pt + 2];
56     p[2] = c[pt + 1];
57     p[3] = c[pt];
58   }
59   return ui;
60 }
61
62 static uint16_t read_uint16(const unsigned char *c, const int pt)
63 {
64   uint32_t ui;
65   char *p = (char *) &ui;
66
67   if (!is_bigendian()) { // le -> le (don't swap)
68     p[0] = c[pt];
69     p[1] = c[pt + 1];
70   } else {
71     p[0] = c[pt + 1];
72     p[1] = c[pt];
73   }
74   return ui;
75 }
76
77 /* libusb transport layer */
78
79 libusb_context* libusb_ctx =  NULL;
80
81 struct stlink_libusb
82 {
83   libusb_device_handle* usb_handle;
84   struct libusb_transfer* req_trans;
85   struct libusb_transfer* rep_trans;
86   unsigned int ep_req;
87   unsigned int ep_rep;
88 };
89
90 struct trans_ctx
91 {
92 #define TRANS_FLAGS_IS_DONE (1 << 0)
93 #define TRANS_FLAGS_HAS_ERROR (1 << 1)
94   volatile unsigned long flags;
95 };
96
97 static void on_trans_done(struct libusb_transfer* trans)
98 {
99   struct trans_ctx* const ctx = trans->user_data;
100
101   if (trans->status != LIBUSB_TRANSFER_COMPLETED)
102     ctx->flags |= TRANS_FLAGS_HAS_ERROR;
103
104   ctx->flags |= TRANS_FLAGS_IS_DONE;
105 }
106
107
108 static int submit_wait(struct libusb_transfer* trans)
109 {
110   struct timeval start;
111   struct timeval now;
112   struct timeval diff;
113   struct trans_ctx trans_ctx;
114   enum libusb_error error;
115
116   trans_ctx.flags = 0;
117
118   /* brief intrusion inside the libusb interface */
119   trans->callback = on_trans_done;
120   trans->user_data = &trans_ctx;
121
122   if ((error = libusb_submit_transfer(trans)))
123   {
124     printf("libusb_submit_transfer(%d)\n", error);
125     return -1;
126   }
127
128   gettimeofday(&start, NULL);
129
130   while (trans_ctx.flags == 0)
131   {
132     struct timeval timeout;
133     timeout.tv_sec = 3;
134     timeout.tv_usec = 0;
135     if (libusb_handle_events_timeout(libusb_ctx, &timeout))
136     {
137       printf("libusb_handle_events()\n");
138       return -1;
139     }
140
141     gettimeofday(&now, NULL);
142     timersub(&now, &start, &diff);
143     if (diff.tv_sec >= 3)
144     {
145       printf("libusb_handle_events() timeout\n");
146       return -1;
147     }
148   }
149
150   if (trans_ctx.flags & TRANS_FLAGS_HAS_ERROR)
151   {
152     printf("libusb_handle_events() | has_error\n");
153     return -1;
154   }
155
156   return 0;
157 }
158
159 static ssize_t send_recv
160 (
161  struct stlink_libusb* handle,
162  unsigned char* txbuf, size_t txsize,
163  unsigned char* rxbuf, size_t rxsize
164 )
165 {
166   /* note: txbuf and rxbuf can point to the same area */
167
168   libusb_fill_bulk_transfer
169   (
170    handle->req_trans,
171    handle->usb_handle,
172    handle->ep_req,
173    txbuf, txsize,
174    NULL, NULL,
175    0
176   );
177
178   printf("submit_wait(req)\n");
179
180   if (submit_wait(handle->req_trans)) return -1;
181
182   /* read the response */
183
184   libusb_fill_bulk_transfer
185   (
186    handle->rep_trans,
187    handle->usb_handle,
188    handle->ep_rep,
189    rxbuf, rxsize,
190    NULL, NULL,
191    0
192   );
193
194   printf("submit_wait(rep)\n");
195
196   if (submit_wait(handle->rep_trans)) return -1;
197
198   return handle->rep_trans->actual_length;
199 }
200
201
202 /* stlink layer independant interface */
203
204 enum transport_type
205 {
206   TRANSPORT_TYPE_ZERO = 0,
207 #if CONFIG_USE_LIBSG
208   TRANSPORT_TYPE_LIBSG,
209 #endif /* CONFIG_USE_LIBSG */
210 #if CONFIG_USE_LIBUSB
211   TRANSPORT_TYPE_LIBUSB,
212 #endif /* CONFIG_USE_LIBUSB */
213   TRANSPORT_TYPE_INVALID
214 };
215
216 struct stlink
217 {
218   enum transport_type tt;
219   union
220   {
221 #if CONFIG_USE_LIBUSB
222     struct stlink_libusb libusb;
223 #endif /* CONFIG_USE_LIBUSB */
224 #if CONFIG_USE_LIBSG
225     void* libsg;
226 #endif /* CONFIG_USE_LIBSG */
227   } transport;
228
229   unsigned char q_buf[64];
230
231   /* layer independant */
232   uint32_t core_id;
233 };
234
235 int stlink_initialize(enum transport_type tt)
236 {
237   switch (tt)
238   {
239 #if CONFIG_USE_LIBUSB
240   case TRANSPORT_TYPE_LIBUSB:
241     {
242       if (libusb_ctx != NULL) return -1;
243       if (libusb_init(&libusb_ctx))
244       {
245         printf("libusb_init()\n");
246         return -1;
247       }
248       break ;
249     }
250 #endif /* CONFIG_USE_LIBUSB */
251
252   default: break ;
253   }
254
255   return 0;
256 }
257
258 void stlink_finalize(enum transport_type tt)
259 {
260   switch (tt)
261   {
262 #if CONFIG_USE_LIBUSB
263   case TRANSPORT_TYPE_LIBUSB:
264     {
265       libusb_exit(libusb_ctx);
266       break ;
267     }
268 #endif /* CONFIG_USE_LIBUSB */
269
270   default: break;
271   }
272 }
273
274 #if CONFIG_USE_LIBUSB
275 static int is_stlink_device(libusb_device* dev)
276 {
277   struct libusb_device_descriptor desc;
278
279   if (libusb_get_device_descriptor(dev, &desc))
280     return 0;
281
282   printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
283  
284   if (desc.idVendor != 0x0483)
285     return 0;
286
287   if (desc.idProduct != 0x3748)
288     return 0;
289
290   return 1;
291 }
292 #endif /* CONFIG_USE_LIBUSB */
293
294 /* fwd decl */
295 void stlink_close(struct stlink*);
296
297 struct stlink* stlink_quirk_open
298 (enum transport_type tt, const char *dev_name, const int verbose)
299 {
300   struct stlink* sl = NULL;
301
302   sl = malloc(sizeof(struct stlink));
303   if (sl == NULL) goto on_error;
304
305   sl->tt = tt;
306
307   switch (tt)
308   {
309 #if CONFIG_USE_LIBUSB
310   case TRANSPORT_TYPE_LIBUSB:
311     {
312       struct stlink_libusb* const slu = &sl->transport.libusb;
313
314       int error = -1;
315
316       libusb_device** devs = NULL;
317       libusb_device* dev;
318       ssize_t i;
319       ssize_t count;
320       int config;
321
322       count = libusb_get_device_list(libusb_ctx, &devs);
323       if (count < 0)
324       {
325         printf("libusb_get_device_list\n");
326         goto on_libusb_error;
327       }
328
329       for (i = 0; i < count; ++i)
330       {
331         dev = devs[i];
332         if (is_stlink_device(dev)) break;
333       }
334       if (i == count) return NULL;
335
336       if (libusb_open(dev, &slu->usb_handle))
337       {
338         printf("libusb_open()\n");
339         goto on_libusb_error;
340       }
341
342       if (libusb_get_configuration(slu->usb_handle, &config))
343       {
344         /* this may fail for a previous configured device */
345         printf("libusb_get_configuration()\n");
346         goto on_libusb_error;
347       }
348
349       if (config != 1)
350       {
351         printf("setting new configuration (%d -> 1)\n", config);
352         if (libusb_set_configuration(slu->usb_handle, 1))
353         {
354           /* this may fail for a previous configured device */
355           printf("libusb_set_configuration()\n");
356           goto on_libusb_error;
357         }
358       }
359
360       if (libusb_claim_interface(slu->usb_handle, 0))
361       {
362         printf("libusb_claim_interface()\n");
363         goto on_libusb_error;
364       }
365
366       slu->req_trans = libusb_alloc_transfer(0);
367       if (slu->req_trans == NULL)
368       {
369         printf("libusb_alloc_transfer\n");
370         goto on_libusb_error;
371       }
372
373       slu->rep_trans = libusb_alloc_transfer(0);
374       if (slu->rep_trans == NULL)
375       {
376         printf("libusb_alloc_transfer\n");
377         goto on_libusb_error;
378       }
379
380       slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
381       slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
382
383       /* libusb_reset_device(slu->usb_handle); */
384
385       /* success */
386       error = 0;
387
388     on_libusb_error:
389       if (devs != NULL) libusb_free_device_list(devs, 1);
390
391       if (error == -1)
392       {
393         stlink_close(sl);
394         return NULL;
395       }
396
397       break ;
398     }
399 #endif /* CONFIG_USE_LIBUSB */
400
401 #if CONFIG_USE_LIBSG
402   case transport_type_libsg:
403     {
404       break ;
405     }
406 #endif /* CONFIG_USE_LIBSG */
407
408   default: break ;
409   }
410
411   /* success */
412   return sl;
413
414  on_error:
415   if (sl != NULL) free(sl);
416   return 0;
417 }
418
419 void stlink_close(struct stlink *sl)
420 {
421   switch (sl->tt)
422   {
423 #if CONFIG_USE_LIBUSB
424   case TRANSPORT_TYPE_LIBUSB:
425     {
426       struct stlink_libusb* const handle = &sl->transport.libusb;
427
428       if (handle->req_trans != NULL)
429         libusb_free_transfer(handle->req_trans);
430
431       if (handle->rep_trans != NULL)
432         libusb_free_transfer(handle->rep_trans);
433
434       if (handle->usb_handle != NULL)
435         libusb_close(handle->usb_handle);
436
437       break ;
438     }
439 #endif /* CONFIG_USE_LIBUSB */
440
441 #if CONFIG_USE_LIBSG
442   case TRANSPORT_TYPE_LIBSG:
443     {
444       break ;
445     }
446 #endif /* CONFIG_USE_LIBSG */
447
448   default: break ;
449   }
450
451   free(sl);
452 }
453
454 void stlink_version(struct stlink* sl)
455 {
456   switch (sl->tt)
457   {
458 #if CONFIG_USE_LIBUSB
459   case TRANSPORT_TYPE_LIBUSB:
460     {
461       struct stlink_libusb* const slu = &sl->transport.libusb;
462       unsigned char* const buf = sl->q_buf;
463       ssize_t size;
464
465       memset(buf, 0, sizeof(sl->q_buf));
466       buf[0] = STLINK_GET_VERSION;
467       buf[1] = 0x80;
468
469       size = send_recv(slu, buf, 16, buf, sizeof(sl->q_buf));
470       if (size == -1)
471       {
472         printf("[!] send_recv\n");
473         return ;
474       }
475
476 #if 1 /* DEBUG */
477       {
478         unsigned int i;
479         for (i = 0; i < size; ++i) printf("%02x", buf[i]);
480         printf("\n");
481       }
482 #endif /* DEBUG */
483
484       break ;
485     }
486 #endif /* CONFIG_USE_LIBUSB */
487
488   default: break ;
489   }
490 }
491
492 int stlink_current_mode(struct stlink *sl)
493 {
494   int mode = -1;
495
496   switch (sl->tt)
497   {
498 #if CONFIG_USE_LIBUSB
499   case TRANSPORT_TYPE_LIBUSB:
500     {
501       struct stlink_libusb* const slu = &sl->transport.libusb;
502       unsigned char* const buf = sl->q_buf; 
503       ssize_t size;
504
505       memset(buf, 0, sizeof(sl->q_buf));
506
507       buf[0] = STLINK_GET_CURRENT_MODE;
508
509       size = send_recv(slu, buf, 16, buf, sizeof(sl->q_buf));
510       if (size == -1)
511       {
512         printf("[!] send_recv\n");
513         return -1;
514       }
515
516       mode = (int)buf[0];
517
518 #if 1 /* DEBUG */
519       printf("mode == 0x%x\n", mode);
520 #endif /* DEBUG */
521
522       break ;
523     }
524 #endif /* CONFIG_USE_LIBUSB */
525
526   default: break ;
527   }
528
529   return mode;
530 }
531
532 void stlink_core_id(struct stlink *sl)
533 {
534   switch (sl->tt)
535   {
536 #if CONFIG_USE_LIBUSB
537   case TRANSPORT_TYPE_LIBUSB:
538     {
539       struct stlink_libusb* const slu = &sl->transport.libusb;
540       unsigned char* const buf = sl->q_buf; 
541       ssize_t size;
542
543       memset(buf, 0, sizeof(sl->q_buf));
544
545       buf[0] = STLINK_DEBUG_READCOREID;
546
547       size = send_recv(slu, buf, sizeof(sl->q_buf), buf, sizeof(sl->q_buf));
548       if (size == -1)
549       {
550         printf("[!] send_recv\n");
551         return ;
552       }
553
554       sl->core_id = read_uint32(buf, 0);
555
556 #if 1 /* DEBUG */
557       printf("core_id == 0x%x\n", sl->core_id);
558 #endif /* DEBUG */
559
560       break ;
561     }
562 #endif /* CONFIG_USE_LIBUSB */
563
564   default: break ;
565   }
566 }
567
568 void stlink_status(struct stlink *sl)
569 {
570   switch (sl->tt)
571   {
572 #if CONFIG_USE_LIBUSB
573   case TRANSPORT_TYPE_LIBUSB:
574     {
575       struct stlink_libusb* const slu = &sl->transport.libusb;
576       unsigned char* const buf = sl->q_buf;
577       ssize_t size;
578
579       memset(buf, 0, sizeof(sl->q_buf));
580
581       buf[0] = STLINK_DEBUG_GETSTATUS;
582
583       size = send_recv(slu, buf, sizeof(sl->q_buf), buf, sizeof(sl->q_buf));
584       if (size == -1)
585       {
586         printf("[!] send_recv\n");
587         return ;
588       }
589
590       /* todo: stlink_core_stat */
591
592 #if 1 /* DEBUG */
593       printf("status == 0x%x\n", buf[0]);
594 #endif /* DEBUG */
595
596       break ;
597     }
598 #endif /* CONFIG_USE_LIBUSB */
599
600   default: break ;
601   }
602 }
603
604 void stlink_enter_swd_mode(struct stlink *sl)
605 {
606   switch (sl->tt)
607   {
608 #if CONFIG_USE_LIBUSB
609   case TRANSPORT_TYPE_LIBUSB:
610     {
611       struct stlink_libusb* const slu = &sl->transport.libusb;
612       unsigned char* const buf = sl->q_buf;
613       ssize_t size;
614
615       memset(buf, 0, sizeof(sl->q_buf));
616
617       buf[0] = STLINK_DEBUG_ENTER;
618       buf[1] = STLINK_DEBUG_ENTER_SWD;
619
620       size = send_recv(slu, buf, sizeof(sl->q_buf), buf, sizeof(sl->q_buf));
621       if (size == -1)
622       {
623         printf("[!] send_recv\n");
624         return ;
625       }
626
627       break ;
628     }
629 #endif /* CONFIG_USE_LIBUSB */
630
631   default: break ;
632   }
633 }
634
635 void stlink_exit_dfu_mode(struct stlink *sl)
636 {
637   switch (sl->tt)
638   {
639 #if CONFIG_USE_LIBUSB
640   case TRANSPORT_TYPE_LIBUSB:
641     {
642       struct stlink_libusb* const slu = &sl->transport.libusb;
643       unsigned char* const buf = sl->q_buf;
644       ssize_t size;
645
646       memset(buf, 0, sizeof(sl->q_buf));
647
648       buf[0] = STLINK_DFU_COMMAND;
649       buf[1] = STLINK_DFU_EXIT;
650
651       size = send_recv(slu, buf, sizeof(sl->q_buf), buf, sizeof(sl->q_buf));
652       if (size == -1)
653       {
654         printf("[!] send_recv\n");
655         return ;
656       }
657
658       break ;
659     }
660 #endif /* CONFIG_USE_LIBUSB */
661
662   default: break ;
663   }
664 }
665
666 void stlink_reset(struct stlink *sl)
667 {
668   switch (sl->tt)
669   {
670 #if CONFIG_USE_LIBUSB
671   case TRANSPORT_TYPE_LIBUSB:
672     {
673       struct stlink_libusb* const slu = &sl->transport.libusb;
674       unsigned char* const buf = sl->q_buf;
675       ssize_t size;
676
677       memset(buf, 0, sizeof(sl->q_buf));
678
679       buf[0] = STLINK_DEBUG_RESETSYS;
680
681       size = send_recv(slu, buf, 2, buf, sizeof(sl->q_buf));
682       if (size == -1)
683       {
684         printf("[!] send_recv\n");
685         return ;
686       }
687
688       break ;
689     }
690 #endif /* CONFIG_USE_LIBUSB */
691
692   default: break ;
693   }
694 }
695
696 void stlink_enter_jtag_mode(struct stlink *sl)
697 {
698 }
699
700 void stlink_exit_debug_mode(struct stlink *sl)
701 {
702 }
703
704
705 /* main */
706
707 int main(int ac, char** av)
708 {
709   struct stlink* sl;
710
711   stlink_initialize(TRANSPORT_TYPE_LIBUSB);
712   sl = stlink_quirk_open(TRANSPORT_TYPE_LIBUSB, NULL, 0);
713   if (sl != NULL)
714   {
715     printf("-- version\n");
716     stlink_version(sl);
717
718     printf("-- exit_dfu_mode\n");
719     stlink_exit_dfu_mode(sl);
720
721     printf("-- enter_swd_mode\n");
722     stlink_enter_swd_mode(sl);
723
724     printf("-- current_mode\n");
725     stlink_current_mode(sl);
726
727     printf("-- core_id\n");
728     stlink_core_id(sl);
729
730     printf("-- status\n");
731     stlink_status(sl);
732
733     printf("-- reset\n");
734     stlink_reset(sl);
735
736     printf("-- status\n");
737     stlink_status(sl);
738
739     stlink_close(sl);
740   }
741   stlink_finalize(TRANSPORT_TYPE_LIBUSB);
742
743   return 0;
744 }