]> git.gag.com Git - fw/stlink/blob - stm32l/src/main.c
[update] submit_wait timeout
[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 & TRANS_FLAGS_IS_DONE))
131   {
132     if (libusb_handle_events(NULL))
133     {
134       printf("libusb_handle_events()\n");
135       return -1;
136     }
137
138     gettimeofday(&now, NULL);
139     timersub(&now, &start, &diff);
140     if (diff.tv_sec >= 3)
141     {
142       printf("libusb_handle_events() timeout\n");
143       return -1;
144     }
145   }
146
147   return 0;
148 }
149
150 static ssize_t send_recv
151 (
152  struct stlink_libusb* handle,
153  unsigned char* txbuf, size_t txsize,
154  unsigned char* rxbuf, size_t rxsize
155 )
156 {
157  /* note: txbuf and rxbuf can point to the same area */
158
159   libusb_fill_bulk_transfer
160   (
161    handle->req_trans,
162    handle->usb_handle,
163    handle->ep_req,
164    txbuf, txsize,
165    NULL, NULL,
166    0
167   );
168
169   printf("submit_wait(req)\n");
170
171   if (submit_wait(handle->req_trans)) return -1;
172
173   /* read the response */
174
175   libusb_fill_bulk_transfer
176   (
177    handle->rep_trans,
178    handle->usb_handle,
179    handle->ep_rep,
180    rxbuf, rxsize,
181    NULL, NULL,
182    0
183   );
184
185   printf("submit_wait(rep)\n");
186
187   if (submit_wait(handle->rep_trans)) return -1;
188
189   return handle->rep_trans->actual_length;
190 }
191
192
193 /* stlink layer independant interface */
194
195 enum transport_type
196 {
197   TRANSPORT_TYPE_ZERO = 0,
198 #if CONFIG_USE_LIBSG
199   TRANSPORT_TYPE_LIBSG,
200 #endif /* CONFIG_USE_LIBSG */
201 #if CONFIG_USE_LIBUSB
202   TRANSPORT_TYPE_LIBUSB,
203 #endif /* CONFIG_USE_LIBUSB */
204   TRANSPORT_TYPE_INVALID
205 };
206
207 struct stlink
208 {
209   enum transport_type tt;
210   union
211   {
212 #if CONFIG_USE_LIBUSB
213     struct stlink_libusb libusb;
214 #endif /* CONFIG_USE_LIBUSB */
215 #if CONFIG_USE_LIBSG
216     void* libsg;
217 #endif /* CONFIG_USE_LIBSG */
218   } transport;
219
220   /* layer independant */
221   uint32_t core_id;
222 };
223
224 int stlink_initialize(enum transport_type tt)
225 {
226   switch (tt)
227   {
228 #if CONFIG_USE_LIBUSB
229   case TRANSPORT_TYPE_LIBUSB:
230     {
231       if (libusb_ctx != NULL) return -1;
232       if (libusb_init(&libusb_ctx))
233       {
234         printf("libusb_init()\n");
235         return -1;
236       }
237       break ;
238     }
239 #endif /* CONFIG_USE_LIBUSB */
240
241   default: break ;
242   }
243
244   return 0;
245 }
246
247 void stlink_finalize(enum transport_type tt)
248 {
249   switch (tt)
250   {
251 #if CONFIG_USE_LIBUSB
252   case TRANSPORT_TYPE_LIBUSB:
253     {
254       libusb_exit(libusb_ctx);
255       break ;
256     }
257 #endif /* CONFIG_USE_LIBUSB */
258
259   default: break;
260   }
261 }
262
263 #if CONFIG_USE_LIBUSB
264 static int is_stlink_device(libusb_device* dev)
265 {
266   struct libusb_device_descriptor desc;
267
268   if (libusb_get_device_descriptor(dev, &desc))
269     return 0;
270
271   printf("device: 0x%04x, 0x%04x\n", desc.idVendor, desc.idProduct);
272  
273   if (desc.idVendor != 0x0483)
274     return 0;
275
276   if (desc.idProduct != 0x3748)
277     return 0;
278
279   return 1;
280 }
281 #endif /* CONFIG_USE_LIBUSB */
282
283 /* fwd decl */
284 void stlink_close(struct stlink*);
285
286 struct stlink* stlink_quirk_open
287 (enum transport_type tt, const char *dev_name, const int verbose)
288 {
289   struct stlink* sl = NULL;
290
291   sl = malloc(sizeof(struct stlink));
292   if (sl == NULL) goto on_error;
293
294   sl->tt = tt;
295
296   switch (tt)
297   {
298 #if CONFIG_USE_LIBUSB
299   case TRANSPORT_TYPE_LIBUSB:
300     {
301       struct stlink_libusb* const slu = &sl->transport.libusb;
302
303       int error = -1;
304
305       libusb_device** devs = NULL;
306       libusb_device* dev;
307       ssize_t i;
308       ssize_t count;
309
310       count = libusb_get_device_list(libusb_ctx, &devs);
311       if (count < 0)
312       {
313         printf("libusb_get_device_list\n");
314         goto on_libusb_error;
315       }
316
317       for (i = 0; i < count; ++i)
318       {
319         dev = devs[i];
320         if (is_stlink_device(dev)) break;
321       }
322       if (i == count) return NULL;
323
324       if (libusb_open(dev, &slu->usb_handle))
325       {
326         printf("libusb_open()\n");
327         goto on_libusb_error;
328       }
329
330       if (libusb_set_configuration(slu->usb_handle, 1))
331       {
332         printf("libusb_set_configuration()\n");
333         goto on_libusb_error;
334       }
335
336       if (libusb_claim_interface(slu->usb_handle, 0))
337       {
338         printf("libusb_claim_interface()\n");
339         goto on_libusb_error;
340       }
341
342       slu->req_trans = libusb_alloc_transfer(0);
343       if (slu->req_trans == NULL)
344       {
345         printf("libusb_alloc_transfer\n");
346         goto on_libusb_error;
347       }
348
349       slu->rep_trans = libusb_alloc_transfer(0);
350       if (slu->rep_trans == NULL)
351       {
352         printf("libusb_alloc_transfer\n");
353         goto on_libusb_error;
354       }
355
356       slu->ep_rep = 1 /* ep rep */ | LIBUSB_ENDPOINT_IN;
357       slu->ep_req = 2 /* ep req */ | LIBUSB_ENDPOINT_OUT;
358
359       /* success */
360       error = 0;
361
362     on_libusb_error:
363       if (devs != NULL) libusb_free_device_list(devs, 1);
364
365       if (error == -1)
366       {
367         stlink_close(sl);
368         return NULL;
369       }
370
371       break ;
372     }
373 #endif /* CONFIG_USE_LIBUSB */
374
375 #if CONFIG_USE_LIBSG
376   case transport_type_libsg:
377     {
378       break ;
379     }
380 #endif /* CONFIG_USE_LIBSG */
381
382   default: break ;
383   }
384
385   /* success */
386   return sl;
387
388  on_error:
389   if (sl != NULL) free(sl);
390   return 0;
391 }
392
393 void stlink_close(struct stlink *sl)
394 {
395   switch (sl->tt)
396   {
397 #if CONFIG_USE_LIBUSB
398   case TRANSPORT_TYPE_LIBUSB:
399     {
400       struct stlink_libusb* const handle = &sl->transport.libusb;
401
402       if (handle->req_trans != NULL)
403         libusb_free_transfer(handle->req_trans);
404
405       if (handle->rep_trans != NULL)
406         libusb_free_transfer(handle->rep_trans);
407
408       if (handle->usb_handle != NULL)
409         libusb_close(handle->usb_handle);
410
411       break ;
412     }
413 #endif /* CONFIG_USE_LIBUSB */
414
415 #if CONFIG_USE_LIBSG
416   case TRANSPORT_TYPE_LIBSG:
417     {
418       break ;
419     }
420 #endif /* CONFIG_USE_LIBSG */
421
422   default: break ;
423   }
424
425   free(sl);
426 }
427
428 void stlink_version(struct stlink* sl)
429 {
430   switch (sl->tt)
431   {
432 #if CONFIG_USE_LIBUSB
433   case TRANSPORT_TYPE_LIBUSB:
434     {
435       struct stlink_libusb* const slu = &sl->transport.libusb;
436
437       ssize_t size;
438       unsigned char buf[64];
439
440       memset(buf, 0, sizeof(buf));
441
442       buf[0] = STLINK_GET_VERSION;
443       buf[1] = 0x80;
444
445       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
446       if (size == -1)
447       {
448         printf("[!] send_recv\n");
449         return ;
450       }
451
452 #if 1 /* DEBUG */
453       {
454         unsigned int i;
455         for (i = 0; i < size; ++i) printf("%02x", buf[i]);
456         printf("\n");
457       }
458 #endif /* DEBUG */
459
460       break ;
461     }
462 #endif /* CONFIG_USE_LIBUSB */
463
464   default: break ;
465   }
466 }
467
468 int stlink_current_mode(struct stlink *sl)
469 {
470   int mode = -1;
471
472   switch (sl->tt)
473   {
474 #if CONFIG_USE_LIBUSB
475   case TRANSPORT_TYPE_LIBUSB:
476     {
477       struct stlink_libusb* const slu = &sl->transport.libusb;
478
479       ssize_t size;
480       unsigned char buf[64];
481
482       memset(buf, 0, sizeof(buf));
483
484       buf[0] = STLINK_GET_CURRENT_MODE;
485
486       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
487       if (size == -1)
488       {
489         printf("[!] send_recv\n");
490         return -1;
491       }
492
493       mode = (int)buf[0];
494
495 #if 1 /* DEBUG */
496       printf("mode == 0x%x\n", mode);
497 #endif /* DEBUG */
498
499       break ;
500     }
501 #endif /* CONFIG_USE_LIBUSB */
502
503   default: break ;
504   }
505
506   return mode;
507 }
508
509 void stlink_core_id(struct stlink *sl)
510 {
511   switch (sl->tt)
512   {
513 #if CONFIG_USE_LIBUSB
514   case TRANSPORT_TYPE_LIBUSB:
515     {
516       struct stlink_libusb* const slu = &sl->transport.libusb;
517
518       ssize_t size;
519       unsigned char buf[64];
520
521       memset(buf, 0, sizeof(buf));
522
523       buf[0] = STLINK_DEBUG_READCOREID;
524
525       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
526       if (size == -1)
527       {
528         printf("[!] send_recv\n");
529         return ;
530       }
531
532       sl->core_id = read_uint32(buf, 0);
533
534 #if 1 /* DEBUG */
535       printf("core_id == 0x%x\n", sl->core_id);
536 #endif /* DEBUG */
537
538       break ;
539     }
540 #endif /* CONFIG_USE_LIBUSB */
541
542   default: break ;
543   }
544 }
545
546 void stlink_status(struct stlink *sl)
547 {
548   switch (sl->tt)
549   {
550 #if CONFIG_USE_LIBUSB
551   case TRANSPORT_TYPE_LIBUSB:
552     {
553       struct stlink_libusb* const slu = &sl->transport.libusb;
554
555       ssize_t size;
556       unsigned char buf[64];
557
558       memset(buf, 0, sizeof(buf));
559
560       buf[0] = STLINK_DEBUG_GETSTATUS;
561
562       size = send_recv(slu, buf, sizeof(buf), buf, sizeof(buf));
563       if (size == -1)
564       {
565         printf("[!] send_recv\n");
566         return ;
567       }
568
569       /* todo: stlink_core_stat */
570
571 #if 1 /* DEBUG */
572       printf("status == 0x%x\n", buf[0]);
573 #endif /* DEBUG */
574
575       break ;
576     }
577 #endif /* CONFIG_USE_LIBUSB */
578
579   default: break ;
580   }
581 }
582
583 void stlink_enter_swd_mode(struct stlink *sl)
584 {
585 }
586
587 void stlink_enter_jtag_mode(struct stlink *sl)
588 {
589 }
590
591 void stlink_exit_debug_mode(struct stlink *sl)
592 {
593 }
594
595
596 /* main */
597
598 int main(int ac, char** av)
599 {
600   struct stlink* sl;
601
602   stlink_initialize(TRANSPORT_TYPE_LIBUSB);
603   sl = stlink_quirk_open(TRANSPORT_TYPE_LIBUSB, NULL, 0);
604   if (sl != NULL)
605   {
606     stlink_version(sl);
607     stlink_status(sl);
608     stlink_current_mode(sl);
609     stlink_core_id(sl);
610     stlink_close(sl);
611   }
612   stlink_finalize(TRANSPORT_TYPE_LIBUSB);
613
614   return 0;
615 }