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 ***************************************************************************/
26 #include "versaloon_include.h"
27 #include "versaloon.h"
28 #include "versaloon_internal.h"
29 #include "usbtoxxx/usbtoxxx.h"
31 uint8_t *versaloon_buf = NULL;
32 uint8_t *versaloon_cmd_buf = NULL;
33 uint16_t versaloon_buf_size;
35 struct versaloon_pending_t versaloon_pending[VERSALOON_MAX_PENDING_NUMBER];
36 uint16_t versaloon_pending_idx = 0;
38 usb_dev_handle *versaloon_usb_device_handle = NULL;
39 static uint32_t versaloon_usb_to = VERSALOON_TIMEOUT;
41 RESULT versaloon_init(void);
42 RESULT versaloon_fini(void);
43 RESULT versaloon_get_target_voltage(uint16_t *voltage);
44 RESULT versaloon_set_target_voltage(uint16_t voltage);
45 RESULT versaloon_delay_ms(uint16_t ms);
46 RESULT versaloon_delay_us(uint16_t us);
47 struct versaloon_interface_t versaloon_interface =
49 .init = versaloon_init,
50 .fini = versaloon_fini,
53 .get = versaloon_get_target_voltage,
54 .set = versaloon_set_target_voltage,
57 .init = usbtogpio_init,
58 .fini = usbtogpio_fini,
59 .config = usbtogpio_config,
64 .delayms = versaloon_delay_ms,
65 .delayus = versaloon_delay_us,
68 .init = usbtoswd_init,
69 .fini = usbtoswd_fini,
70 .config = usbtoswd_config,
71 .seqout = usbtoswd_seqout,
72 .seqin = usbtoswd_seqin,
73 .transact = usbtoswd_transact,
76 .init = usbtojtagraw_init,
77 .fini = usbtojtagraw_fini,
78 .config = usbtojtagraw_config,
79 .execute = usbtojtagraw_execute,
81 .peripheral_commit = usbtoxxx_execute_command,
86 .ep_out = VERSALOON_OUTP,
87 .ep_in = VERSALOON_INP,
88 .interface = VERSALOON_IFACE,
95 static uint32_t versaloon_pending_id = 0;
96 static versaloon_callback_t versaloon_callback = NULL;
97 static void *versaloon_extra_data = NULL;
98 static struct versaloon_want_pos_t *versaloon_want_pos = NULL;
99 void versaloon_set_pending_id(uint32_t id)
101 versaloon_pending_id = id;
103 void versaloon_set_callback(versaloon_callback_t callback)
105 versaloon_callback = callback;
107 void versaloon_set_extra_data(void * p)
109 versaloon_extra_data = p;
112 void versaloon_free_want_pos(void)
115 struct versaloon_want_pos_t *tmp, *free_tmp;
117 tmp = versaloon_want_pos;
124 versaloon_want_pos = NULL;
126 for (i = 0; i < dimof(versaloon_pending); i++)
128 tmp = versaloon_pending[i].pos;
135 versaloon_pending[i].pos = NULL;
139 RESULT versaloon_add_want_pos(uint16_t offset, uint16_t size, uint8_t *buff)
141 struct versaloon_want_pos_t *new_pos = NULL;
143 new_pos = (struct versaloon_want_pos_t *)malloc(sizeof(*new_pos));
146 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
147 return ERRCODE_NOT_ENOUGH_MEMORY;
149 new_pos->offset = offset;
150 new_pos->size = size;
151 new_pos->buff = buff;
152 new_pos->next = NULL;
154 if (NULL == versaloon_want_pos)
156 versaloon_want_pos = new_pos;
160 struct versaloon_want_pos_t *tmp = versaloon_want_pos;
162 while (tmp->next != NULL)
172 RESULT versaloon_add_pending(uint8_t type, uint8_t cmd, uint16_t actual_szie,
173 uint16_t want_pos, uint16_t want_size, uint8_t *buffer, uint8_t collect)
176 if (versaloon_pending_idx >= VERSALOON_MAX_PENDING_NUMBER)
178 LOG_BUG(ERRMSG_INVALID_INDEX, versaloon_pending_idx,
179 "versaloon pending data");
184 versaloon_pending[versaloon_pending_idx].type = type;
185 versaloon_pending[versaloon_pending_idx].cmd = cmd;
186 versaloon_pending[versaloon_pending_idx].actual_data_size = actual_szie;
187 versaloon_pending[versaloon_pending_idx].want_data_pos = want_pos;
188 versaloon_pending[versaloon_pending_idx].want_data_size = want_size;
189 versaloon_pending[versaloon_pending_idx].data_buffer = buffer;
190 versaloon_pending[versaloon_pending_idx].collect = collect;
191 versaloon_pending[versaloon_pending_idx].id = versaloon_pending_id;
192 versaloon_pending_id = 0;
193 versaloon_pending[versaloon_pending_idx].extra_data = versaloon_extra_data;
194 versaloon_extra_data = NULL;
195 versaloon_pending[versaloon_pending_idx].callback = versaloon_callback;
196 versaloon_callback = NULL;
197 versaloon_pending[versaloon_pending_idx].pos = versaloon_want_pos;
198 versaloon_want_pos = NULL;
199 versaloon_pending_idx++;
204 RESULT versaloon_send_command(uint16_t out_len, uint16_t *inlen)
209 if (NULL == versaloon_buf)
211 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
212 return ERRCODE_INVALID_BUFFER;
214 if ((0 == out_len) || (out_len > versaloon_interface.usb_setting.buf_size))
216 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
217 return ERRCODE_INVALID_PARAMETER;
221 ret = usb_bulk_write(versaloon_usb_device_handle,
222 versaloon_interface.usb_setting.ep_out, (char *)versaloon_buf,
223 out_len, versaloon_usb_to);
226 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "send usb data",
228 return ERRCODE_FAILURE_OPERATION;
233 ret = usb_bulk_read(versaloon_usb_device_handle,
234 versaloon_interface.usb_setting.ep_in, (char *)versaloon_buf,
235 versaloon_interface.usb_setting.buf_size, versaloon_usb_to);
238 *inlen = (uint16_t)ret;
243 LOG_ERROR(ERRMSG_FAILURE_OPERATION_ERRSTRING, "receive usb data",
254 #define VERSALOON_RETRY_CNT 10
255 RESULT versaloon_init(void)
259 uint32_t timeout_tmp;
261 // malloc temporary buffer
263 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size);
264 if (NULL == versaloon_buf)
266 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
267 return ERRCODE_NOT_ENOUGH_MEMORY;
270 // connect to versaloon
271 timeout_tmp = versaloon_usb_to;
272 // not output error message when connectting
273 // 100ms delay when connect
274 versaloon_usb_to = 100;
275 for (retry = 0; retry < VERSALOON_RETRY_CNT; retry++)
277 versaloon_buf[0] = VERSALOON_GET_INFO;
278 if ((ERROR_OK == versaloon_send_command(1, &ret)) && (ret >= 3))
283 versaloon_usb_to = timeout_tmp;
284 if (VERSALOON_RETRY_CNT == retry)
287 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
288 return ERRCODE_FAILURE_OPERATION;
291 versaloon_buf[ret] = 0;
292 versaloon_buf_size = versaloon_buf[0] + (versaloon_buf[1] << 8);
293 versaloon_interface.usb_setting.buf_size = versaloon_buf_size;
294 LOG_INFO("%s", versaloon_buf + 2);
296 // free temporary buffer
298 versaloon_buf = NULL;
301 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size);
302 if (NULL == versaloon_buf)
305 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
306 return ERRCODE_NOT_ENOUGH_MEMORY;
309 (uint8_t *)malloc(versaloon_interface.usb_setting.buf_size - 3);
310 if (NULL == versaloon_cmd_buf)
313 LOG_ERROR(ERRMSG_NOT_ENOUGH_MEMORY);
314 return ERRCODE_NOT_ENOUGH_MEMORY;
316 if (ERROR_OK != usbtoxxx_init())
318 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "initialize usbtoxxx");
321 return versaloon_get_target_voltage(&ret);
324 RESULT versaloon_fini(void)
326 if (versaloon_usb_device_handle != NULL)
329 versaloon_free_want_pos();
331 versaloon_usb_device_handle = NULL;
333 if (versaloon_buf != NULL)
336 versaloon_buf = NULL;
338 if (versaloon_cmd_buf != NULL)
340 free(versaloon_cmd_buf);
341 versaloon_cmd_buf = NULL;
348 RESULT versaloon_set_target_voltage(uint16_t voltage)
352 usbtopwr_output(0, voltage);
355 return usbtoxxx_execute_command();
358 RESULT versaloon_get_target_voltage(uint16_t *voltage)
363 if (NULL == versaloon_buf)
365 LOG_BUG(ERRMSG_INVALID_BUFFER, TO_STR(versaloon_buf));
366 return ERRCODE_INVALID_BUFFER;
370 LOG_BUG(ERRMSG_INVALID_PARAMETER, __FUNCTION__);
371 return ERRCODE_INVALID_PARAMETER;
375 versaloon_buf[0] = VERSALOON_GET_TVCC;
377 if ((ERROR_OK != versaloon_send_command(1, &inlen)) || (inlen != 2))
379 LOG_ERROR(ERRMSG_FAILURE_OPERATION, "communicate with versaloon");
380 return ERRCODE_FAILURE_OPERATION;
384 *voltage = versaloon_buf[0] + (versaloon_buf[1] << 8);
389 RESULT versaloon_delay_ms(uint16_t ms)
391 return usbtodelay_delay(ms | 0x8000);
394 RESULT versaloon_delay_us(uint16_t us)
396 return usbtodelay_delay(us & 0x7FFF);