7deb3284c64e50e90fd282f8238e34b443b8d4fc
[fw/stlink] / stm32l / src / main.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5 #include <sys/types.h>
6 #include <libusb-1.0/libusb.h>
7 #include "stlink-hw.h"
8
9 /* endianess related */
10 static inline unsigned int is_bigendian(void)
11 {
12   static volatile const unsigned int i = 1;
13   return *(volatile const char*) &i == 0;
14 }
15
16 static void write_uint32(unsigned char* buf, uint32_t ui)
17 {
18   if (!is_bigendian()) { // le -> le (don't swap)
19     buf[0] = ((unsigned char*) &ui)[0];
20     buf[1] = ((unsigned char*) &ui)[1];
21     buf[2] = ((unsigned char*) &ui)[2];
22     buf[3] = ((unsigned char*) &ui)[3];
23   } else {
24     buf[0] = ((unsigned char*) &ui)[3];
25     buf[1] = ((unsigned char*) &ui)[2];
26     buf[2] = ((unsigned char*) &ui)[1];
27     buf[3] = ((unsigned char*) &ui)[0];
28   }
29 }
30
31 static void write_uint16(unsigned char* buf, uint16_t ui)
32 {
33   if (!is_bigendian()) { // le -> le (don't swap)
34     buf[0] = ((unsigned char*) &ui)[0];
35     buf[1] = ((unsigned char*) &ui)[1];
36   } else {
37     buf[0] = ((unsigned char*) &ui)[1];
38     buf[1] = ((unsigned char*) &ui)[0];
39   }
40 }
41
42 static uint32_t read_uint32(const unsigned char *c, const int pt)
43 {
44   uint32_t ui;
45   char *p = (char *) &ui;
46
47   if (!is_bigendian()) { // le -> le (don't swap)
48     p[0] = c[pt];
49     p[1] = c[pt + 1];
50     p[2] = c[pt + 2];
51     p[3] = c[pt + 3];
52   } else {
53     p[0] = c[pt + 3];
54     p[1] = c[pt + 2];
55     p[2] = c[pt + 1];
56     p[3] = c[pt];
57   }
58   return ui;
59 }
60
61 static uint16_t read_uint16(const unsigned char *c, const int pt)
62 {
63   uint32_t ui;
64   char *p = (char *) &ui;
65
66   if (!is_bigendian()) { // le -> le (don't swap)
67     p[0] = c[pt];
68     p[1] = c[pt + 1];
69   } else {
70     p[0] = c[pt + 1];
71     p[1] = c[pt];
72   }
73   return ui;
74 }
75
76 /* libusb transport layer */
77
78 libusb_context* libusb_ctx =  NULL;
79
80 struct stlink_libusb
81 {
82   libusb_device_handle* usb_handle;
83   struct libusb_transfer* req_trans;
84   struct libusb_transfer* rep_trans;
85   unsigned int ep_req;
86   unsigned int ep_rep;
87 };
88
89 struct trans_ctx
90 {
91 #define TRANS_FLAGS_IS_DONE (1 << 0)
92 #define TRANS_FLAGS_HAS_ERROR (1 << 1)
93   volatile unsigned long flags;
94 };
95
96 static void on_trans_done(struct libusb_transfer* trans)
97 {
98   struct trans_ctx* const ctx = trans->user_data;
99
100   if (trans->status != LIBUSB_TRANSFER_COMPLETED)
101     ctx->flags |= TRANS_FLAGS_HAS_ERROR;
102
103   ctx->flags = TRANS_FLAGS_IS_DONE;
104 }
105
106
107 static int submit_wait(struct libusb_transfer* trans)
108 {
109   struct trans_ctx trans_ctx;
110   enum libusb_error error;
111
112   trans_ctx.flags = 0;
113
114   /* brief intrusion inside the libusb interface */
115   trans->callback = on_trans_done;
116   trans->user_data = &trans_ctx;
117
118   if ((error = libusb_submit_transfer(trans)))
119   {
120     printf("libusb_submit_transfer(%d)\n", error);
121     return -1;
122   }
123
124   while (!(trans_ctx.flags & TRANS_FLAGS_IS_DONE))
125   {
126     if (libusb_handle_events(NULL))
127     {
128       printf("libusb_handle_events()\n");
129       return -1;
130     }
131   }
132
133   return 0;
134 }
135
136 static ssize_t send_recv
137 (
138  struct stlink_libusb* handle,
139  unsigned char* txbuf, size_t txsize,
140  unsigned char* rxbuf, size_t rxsize
141 )
142 {
143  /* note: txbuf and rxbuf can point to the same area */
144
145   libusb_fill_bulk_transfer
146   (
147    handle->req_trans,
148    handle->usb_handle,
149    handle->ep_req,
150    txbuf, txsize,
151    NULL, NULL,
152    0
153   );
154
155   printf("submit_wait(req)\n");
156
157   if (submit_wait(handle->req_trans)) return -1;
158
159   /* read the response */
160
161   libusb_fill_bulk_transfer
162   (
163    handle->rep_trans,
164    handle->usb_handle,
165    handle->ep_rep,
166    rxbuf, rxsize,
167    NULL, NULL,
168    0
169   );
170
171   printf("submit_wait(rep)\n");
172
173   if (submit_wait(handle->rep_trans)) return -1;
174
175   return handle->rep_trans->actual_length;
176 }
177
178
179 /* stlink layer independant interface */
180
181 enum transport_type
182 {
183   TRANSPORT_TYPE_ZERO = 0,
184 #if CONFIG_USE_LIBSG
185   TRANSPORT_TYPE_LIBSG,
186 #endif /* CONFIG_USE_LIBSG */
187 #if CONFIG_USE_LIBUSB
188   TRANSPORT_TYPE_LIBUSB,
189 #endif /* CONFIG_USE_LIBUSB */
190   TRANSPORT_TYPE_INVALID
191 };
192
193 struct stlink
194 {
195   enum transport_type tt;
196   union
197   {
198 #if CONFIG_USE_LIBUSB
199     struct stlink_libusb libusb;
200 #endif /* CONFIG_USE_LIBUSB */
201 #if CONFIG_USE_LIBSG
202     void* libsg;
203 #endif /* CONFIG_USE_LIBSG */
204   } transport;
205
206   /* layer independant */
207   uint32_t core_id;
208 };
209
210 int stlink_initialize(enum transport_type tt)
211 {
212   switch (tt)
213   {
214 #if CONFIG_USE_LIBUSB
215   case TRANSPORT_TYPE_LIBUSB:
216     {
217       if (libusb_ctx != NULL) return -1;
218       if (libusb_init(&libusb_ctx))
219       {
220         printf("libusb_init()\n");
221         return -1;
222       }
223       break ;
224     }
225 #endif /* CONFIG_USE_LIBUSB */
226
227   default: break ;
228   }
229
230   return 0;
231 }
232
233 void stlink_finalize(enum transport_type tt)
234 {
235   switch (tt)
236   {
237 #if CONFIG_USE_LIBUSB
238   case TRANSPORT_TYPE_LIBUSB:
239     {
240       libusb_exit(libusb_ctx);
241       break ;
242     }
243 #endif /* CONFIG_USE_LIBUSB */
244
245   default: break;
246   }
247 }
248
249 #if CONFIG_USE_LIBUSB
250 static int is_stlink_device(libusb_device* dev)
251 {
252   struct libusb_device_descriptor desc;
253
254   if (libusb_get_device_descriptor(dev, &desc))
255     return 0;
256
257   printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
258  
259   if (desc.idVendor != 0x0483)
260     return 0;
261
262   if (desc.idProduct != 0x3748)
263     return 0;
264
265   return 1;
266 }
267 #endif /* CONFIG_USE_LIBUSB */
268
269 /* fwd decl */
270 void stlink_close(struct stlink*);
271
272 struct stlink* stlink_quirk_open
273 (enum transport_type tt, const char *dev_name, const int verbose)
274 {
275   struct stlink* sl = NULL;
276
277   sl = malloc(sizeof(struct stlink));
278   if (sl == NULL) goto on_error;
279
280   sl->tt = tt;
281
282   switch (tt)
283   {
284 #if CONFIG_USE_LIBUSB
285   case TRANSPORT_TYPE_LIBUSB:
286     {
287       struct stlink_libusb* const slu = &sl->transport.libusb;
288
289       int error = -1;
290
291       libusb_device** devs = NULL;
292       libusb_device* dev;
293       ssize_t i;
294       ssize_t count;
295
296       count = libusb_get_device_list(libusb_ctx, &devs);
297       if (count < 0)
298       {
299         printf("libusb_get_device_list\n");
300         goto on_libusb_error;
301       }
302
303       for (i = 0; i < count; ++i)
304       {
305         dev = devs[i];
306         if (is_stlink_device(dev)) break;
307       }
308       if (i == count) return NULL;
309
310       if (libusb_open(dev, &slu->usb_handle))
311       {
312         printf("libusb_open()\n");
313         goto on_libusb_error;
314       }
315
316       if (libusb_set_configuration(slu->usb_handle, 1))
317       {
318         printf("libusb_set_configuration()\n");
319         goto on_libusb_error;
320       }
321
322       if (libusb_claim_interface(slu->usb_handle, 0))
323       {
324         printf("libusb_claim_interface()\n");
325         goto on_libusb_error;
326       }
327
328       slu->req_trans = libusb_alloc_transfer(0);
329       if (slu->req_trans == NULL)
330       {
331         printf("libusb_alloc_transfer\n");
332         goto on_libusb_error;
333       }
334
335       slu->rep_trans = libusb_alloc_transfer(0);
336       if (slu->rep_trans == NULL)
337       {
338         printf("libusb_alloc_transfer\n");
339         goto on_libusb_error;
340       }
341
342       slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
343       slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
344
345       /* success */
346       error = 0;
347
348     on_libusb_error:
349       if (devs != NULL) libusb_free_device_list(devs, 1);
350
351       if (error == -1)
352       {
353         stlink_close(sl);
354         return NULL;
355       }
356
357       break ;
358     }
359 #endif /* CONFIG_USE_LIBUSB */
360
361 #if CONFIG_USE_LIBSG
362   case transport_type_libsg:
363     {
364       break ;
365     }
366 #endif /* CONFIG_USE_LIBSG */
367
368   default: break ;
369   }
370
371   /* success */
372   return sl;
373
374  on_error:
375   if (sl != NULL) free(sl);
376   return 0;
377 }
378
379 void stlink_close(struct stlink *sl)
380 {
381   switch (sl->tt)
382   {
383 #if CONFIG_USE_LIBUSB
384   case TRANSPORT_TYPE_LIBUSB:
385     {
386       struct stlink_libusb* const handle = &sl->transport.libusb;
387
388       if (handle->req_trans != NULL)
389         libusb_free_transfer(handle->req_trans);
390
391       if (handle->rep_trans != NULL)
392         libusb_free_transfer(handle->rep_trans);
393
394       if (handle->usb_handle != NULL)
395         libusb_close(handle->usb_handle);
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   free(sl);
412 }
413
414 void stlink_version(struct stlink* sl)
415 {
416   switch (sl->tt)
417   {
418 #if CONFIG_USE_LIBUSB
419   case TRANSPORT_TYPE_LIBUSB:
420     {
421       struct stlink_libusb* const slu = &sl->transport.libusb;
422
423       ssize_t size;
424       unsigned char buf[64];
425
426       memset(buf, 0, sizeof(buf));
427
428       buf[0] = STLINK_GET_VERSION;
429       buf[1] = 0x80;
430
431       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
432       if (size == -1)
433       {
434         printf("[!] send_recv\n");
435         return ;
436       }
437
438 #if 1 /* DEBUG */
439       {
440         unsigned int i;
441         for (i = 0; i < size; ++i) printf("%02x", buf[i]);
442         printf("\n");
443       }
444 #endif /* DEBUG */
445
446       break ;
447     }
448 #endif /* CONFIG_USE_LIBUSB */
449
450   default: break ;
451   }
452 }
453
454 int stlink_current_mode(struct stlink *sl)
455 {
456   int mode = -1;
457
458   switch (sl->tt)
459   {
460 #if CONFIG_USE_LIBUSB
461   case TRANSPORT_TYPE_LIBUSB:
462     {
463       struct stlink_libusb* const slu = &sl->transport.libusb;
464
465       ssize_t size;
466       unsigned char buf[64];
467
468       memset(buf, 0, sizeof(buf));
469
470       buf[0] = STLINK_GET_CURRENT_MODE;
471
472       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
473       if (size == -1)
474       {
475         printf("[!] send_recv\n");
476         return -1;
477       }
478
479       mode = (int)buf[0];
480
481 #if 1 /* DEBUG */
482       printf("mode == 0x%x\n", mode);
483 #endif /* DEBUG */
484
485       break ;
486     }
487 #endif /* CONFIG_USE_LIBUSB */
488
489   default: break ;
490   }
491
492   return mode;
493 }
494
495 void stlink_core_id(struct stlink *sl)
496 {
497   switch (sl->tt)
498   {
499 #if CONFIG_USE_LIBUSB
500   case TRANSPORT_TYPE_LIBUSB:
501     {
502       struct stlink_libusb* const slu = &sl->transport.libusb;
503
504       ssize_t size;
505       unsigned char buf[64];
506
507       memset(buf, 0, sizeof(buf));
508
509       buf[0] = STLINK_DEBUG_READCOREID;
510
511       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
512       if (size == -1)
513       {
514         printf("[!] send_recv\n");
515         return ;
516       }
517
518       sl->core_id = read_uint32(buf, 0);
519
520 #if 1 /* DEBUG */
521       printf("core_id == 0x%x\n", sl->core_id);
522 #endif /* DEBUG */
523
524       break ;
525     }
526 #endif /* CONFIG_USE_LIBUSB */
527
528   default: break ;
529   }
530 }
531
532 void stlink_status(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
541       ssize_t size;
542       unsigned char buf[64];
543
544       memset(buf, 0, sizeof(buf));
545
546       buf[0] = STLINK_DEBUG_GETSTATUS;
547
548       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
549       if (size == -1)
550       {
551         printf("[!] send_recv\n");
552         return ;
553       }
554
555       /* todo: stlink_core_stat */
556
557 #if 1 /* DEBUG */
558       printf("status == 0x%x\n", buf[0]);
559 #endif /* DEBUG */
560
561       break ;
562     }
563 #endif /* CONFIG_USE_LIBUSB */
564
565   default: break ;
566   }
567 }
568
569 void stlink_enter_swd_mode(struct stlink *sl)
570 {
571 }
572
573 void stlink_enter_jtag_mode(struct stlink *sl)
574 {
575 }
576
577 void stlink_exit_debug_mode(struct stlink *sl)
578 {
579 }
580
581
582 /* main */
583
584 int main(int ac, char** av)
585 {
586   struct stlink* sl;
587
588   stlink_initialize(TRANSPORT_TYPE_LIBUSB);
589   sl = stlink_quirk_open(TRANSPORT_TYPE_LIBUSB, NULL, 0);
590   if (sl != NULL)
591   {
592     stlink_version(sl);
593     stlink_status(sl);
594     stlink_current_mode(sl);
595     stlink_core_id(sl);
596     stlink_close(sl);
597   }
598   stlink_finalize(TRANSPORT_TYPE_LIBUSB);
599
600   return 0;
601 }