1 /***************************************************************************
2 * Copyright (C) 2009 - 2010 by Simon Qian <SimonQian@SimonQian.com> *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
18 ***************************************************************************/
27 #include "versaloon_include.h"
28 #include "versaloon.h"
29 #include "versaloon_internal.h"
30 #include "usbtoxxx/usbtoxxx.h"
32 uint8_t *versaloon_buf
;
33 uint8_t *versaloon_cmd_buf
;
34 uint16_t versaloon_buf_size
;
36 struct versaloon_pending_t versaloon_pending
[VERSALOON_MAX_PENDING_NUMBER
];
37 uint16_t versaloon_pending_idx
;
39 usb_dev_handle
*versaloon_usb_device_handle
;
40 static uint32_t versaloon_usb_to
= VERSALOON_TIMEOUT
;
42 RESULT
versaloon_init(void);
43 RESULT
versaloon_fini(void);
44 RESULT
versaloon_get_target_voltage(uint16_t *voltage
);
45 RESULT
versaloon_set_target_voltage(uint16_t voltage
);
46 RESULT
versaloon_delay_ms(uint16_t ms
);
47 RESULT
versaloon_delay_us(uint16_t us
);
49 struct versaloon_interface_t versaloon_interface
= {
50 .init
= versaloon_init
,
51 .fini
= versaloon_fini
,
53 { /* target_voltage */
54 .get
= versaloon_get_target_voltage
,
55 .set
= versaloon_set_target_voltage
,
58 .init
= usbtogpio_init
,
59 .fini
= usbtogpio_fini
,
60 .config
= usbtogpio_config
,
65 .delayms
= versaloon_delay_ms
,
66 .delayus
= versaloon_delay_us
,
69 .init
= usbtoswd_init
,
70 .fini
= usbtoswd_fini
,
71 .config
= usbtoswd_config
,
72 .seqout
= usbtoswd_seqout
,
73 .seqin
= usbtoswd_seqin
,
74 .transact
= usbtoswd_transact
,
77 .init
= usbtojtagraw_init
,
78 .fini
= usbtojtagraw_fini
,
79 .config
= usbtojtagraw_config
,
80 .execute
= usbtojtagraw_execute
,
82 .peripheral_commit
= usbtoxxx_execute_command
,
87 .ep_out
= VERSALOON_OUTP
,
88 .ep_in
= VERSALOON_INP
,
89 .interface
= VERSALOON_IFACE
,
96 static uint32_t versaloon_pending_id
;
97 static versaloon_callback_t versaloon_callback
;
98 static void *versaloon_extra_data
;
99 static struct versaloon_want_pos_t
*versaloon_want_pos
;
101 void versaloon_set_pending_id(uint32_t id
)
103 versaloon_pending_id
= id
;
105 void versaloon_set_callback(versaloon_callback_t callback
)
107 versaloon_callback
= callback
;
109 void versaloon_set_extra_data(void *p
)
111 versaloon_extra_data
= p
;
114 void versaloon_free_want_pos(void)
117 struct versaloon_want_pos_t
*tmp
, *free_tmp
;
119 tmp
= versaloon_want_pos
;
120 while (tmp
!= NULL
) {
125 versaloon_want_pos
= NULL
;
127 for (i
= 0; i
< dimof(versaloon_pending
); i
++) {
128 tmp
= versaloon_pending
[i
].pos
;
129 while (tmp
!= NULL
) {
134 versaloon_pending
[i
].pos
= NULL
;
138 RESULT
versaloon_add_want_pos(uint16_t offset
, uint16_t size
, uint8_t *buff
)
140 struct versaloon_want_pos_t
*new_pos
= NULL
;
142 new_pos
= (struct versaloon_want_pos_t
*)malloc(sizeof(*new_pos
));
143 if (NULL
== new_pos
) {
144 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY
);
145 return ERRCODE_NOT_ENOUGH_MEMORY
;
147 new_pos
->offset
= offset
;
148 new_pos
->size
= size
;
149 new_pos
->buff
= buff
;
150 new_pos
->next
= NULL
;
152 if (NULL
== versaloon_want_pos
)
153 versaloon_want_pos
= new_pos
;
155 struct versaloon_want_pos_t
*tmp
= versaloon_want_pos
;
157 while (tmp
->next
!= NULL
)
165 RESULT
versaloon_add_pending(uint8_t type
, uint8_t cmd
, uint16_t actual_szie
,
166 uint16_t want_pos
, uint16_t want_size
, uint8_t *buffer
, uint8_t collect
)
169 if (versaloon_pending_idx
>= VERSALOON_MAX_PENDING_NUMBER
) {
170 LOG_BUG(ERRMSG_INVALID_INDEX
, versaloon_pending_idx
,
171 "versaloon pending data");
176 versaloon_pending
[versaloon_pending_idx
].type
= type
;
177 versaloon_pending
[versaloon_pending_idx
].cmd
= cmd
;
178 versaloon_pending
[versaloon_pending_idx
].actual_data_size
= actual_szie
;
179 versaloon_pending
[versaloon_pending_idx
].want_data_pos
= want_pos
;
180 versaloon_pending
[versaloon_pending_idx
].want_data_size
= want_size
;
181 versaloon_pending
[versaloon_pending_idx
].data_buffer
= buffer
;
182 versaloon_pending
[versaloon_pending_idx
].collect
= collect
;
183 versaloon_pending
[versaloon_pending_idx
].id
= versaloon_pending_id
;
184 versaloon_pending_id
= 0;
185 versaloon_pending
[versaloon_pending_idx
].extra_data
= versaloon_extra_data
;
186 versaloon_extra_data
= NULL
;
187 versaloon_pending
[versaloon_pending_idx
].callback
= versaloon_callback
;
188 versaloon_callback
= NULL
;
189 versaloon_pending
[versaloon_pending_idx
].pos
= versaloon_want_pos
;
190 versaloon_want_pos
= NULL
;
191 versaloon_pending_idx
++;
196 RESULT
versaloon_send_command(uint16_t out_len
, uint16_t *inlen
)
201 if (NULL
== versaloon_buf
) {
202 LOG_BUG(ERRMSG_INVALID_BUFFER
, TO_STR(versaloon_buf
));
203 return ERRCODE_INVALID_BUFFER
;
205 if ((0 == out_len
) || (out_len
> versaloon_interface
.usb_setting
.buf_size
)) {
206 LOG_BUG(ERRMSG_INVALID_PARAMETER
, __func__
);
207 return ERRCODE_INVALID_PARAMETER
;
211 ret
= usb_bulk_write(versaloon_usb_device_handle
,
212 versaloon_interface
.usb_setting
.ep_out
, (char *)versaloon_buf
,
213 out_len
, versaloon_usb_to
);
214 if (ret
!= out_len
) {
215 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING
, "send usb data",
217 return ERRCODE_FAILURE_OPERATION
;
221 ret
= usb_bulk_read(versaloon_usb_device_handle
,
222 versaloon_interface
.usb_setting
.ep_in
, (char *)versaloon_buf
,
223 versaloon_interface
.usb_setting
.buf_size
, versaloon_usb_to
);
225 *inlen
= (uint16_t)ret
;
228 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING
, "receive usb data",
236 #define VERSALOON_RETRY_CNT 10
237 RESULT
versaloon_init(void)
241 uint32_t timeout_tmp
;
243 /* malloc temporary buffer */
245 (uint8_t *)malloc(versaloon_interface
.usb_setting
.buf_size
);
246 if (NULL
== versaloon_buf
) {
247 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY
);
248 return ERRCODE_NOT_ENOUGH_MEMORY
;
251 /* connect to versaloon */
252 timeout_tmp
= versaloon_usb_to
;
253 /* not output error message when connectting */
254 /* 100ms delay when connect */
255 versaloon_usb_to
= 100;
256 for (retry
= 0; retry
< VERSALOON_RETRY_CNT
; retry
++) {
257 versaloon_buf
[0] = VERSALOON_GET_INFO
;
258 if ((ERROR_OK
== versaloon_send_command(1, &ret
)) && (ret
>= 3))
261 versaloon_usb_to
= timeout_tmp
;
262 if (VERSALOON_RETRY_CNT
== retry
) {
264 LOG_ERROR(ERRMSG_FAILURE_OPERATION
, "communicate with versaloon");
265 return ERRCODE_FAILURE_OPERATION
;
268 versaloon_buf
[ret
] = 0;
269 versaloon_buf_size
= versaloon_buf
[0] + (versaloon_buf
[1] << 8);
270 versaloon_interface
.usb_setting
.buf_size
= versaloon_buf_size
;
271 LOG_INFO("%s", versaloon_buf
+ 2);
273 /* free temporary buffer */
275 versaloon_buf
= NULL
;
278 (uint8_t *)malloc(versaloon_interface
.usb_setting
.buf_size
);
279 if (NULL
== versaloon_buf
) {
281 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY
);
282 return ERRCODE_NOT_ENOUGH_MEMORY
;
285 (uint8_t *)malloc(versaloon_interface
.usb_setting
.buf_size
- 3);
286 if (NULL
== versaloon_cmd_buf
) {
288 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY
);
289 return ERRCODE_NOT_ENOUGH_MEMORY
;
291 if (ERROR_OK
!= usbtoxxx_init()) {
292 LOG_ERROR(ERRMSG_FAILURE_OPERATION
, "initialize usbtoxxx");
295 return versaloon_get_target_voltage(&ret
);
298 RESULT
versaloon_fini(void)
300 if (versaloon_usb_device_handle
!= NULL
) {
302 versaloon_free_want_pos();
304 versaloon_usb_device_handle
= NULL
;
306 if (versaloon_buf
!= NULL
) {
308 versaloon_buf
= NULL
;
310 if (versaloon_cmd_buf
!= NULL
) {
311 free(versaloon_cmd_buf
);
312 versaloon_cmd_buf
= NULL
;
319 RESULT
versaloon_set_target_voltage(uint16_t voltage
)
323 usbtopwr_output(0, voltage
);
326 return usbtoxxx_execute_command();
329 RESULT
versaloon_get_target_voltage(uint16_t *voltage
)
334 if (NULL
== versaloon_buf
) {
335 LOG_BUG(ERRMSG_INVALID_BUFFER
, TO_STR(versaloon_buf
));
336 return ERRCODE_INVALID_BUFFER
;
338 if (NULL
== voltage
) {
339 LOG_BUG(ERRMSG_INVALID_PARAMETER
, __func__
);
340 return ERRCODE_INVALID_PARAMETER
;
344 versaloon_buf
[0] = VERSALOON_GET_TVCC
;
346 if ((ERROR_OK
!= versaloon_send_command(1, &inlen
)) || (inlen
!= 2)) {
347 LOG_ERROR(ERRMSG_FAILURE_OPERATION
, "communicate with versaloon");
348 return ERRCODE_FAILURE_OPERATION
;
350 *voltage
= versaloon_buf
[0] + (versaloon_buf
[1] << 8);
355 RESULT
versaloon_delay_ms(uint16_t ms
)
357 return usbtodelay_delay(ms
| 0x8000);
360 RESULT
versaloon_delay_us(uint16_t us
)
362 return usbtodelay_delay(us
& 0x7FFF);