blob: 07c5af864cf8e4a52d179a2caecc4d13223f658d [file] [log] [blame]
Kévin Redon69b92d92019-01-24 16:39:20 +01001/*
Kévin Redon78d2f442019-01-24 18:45:59 +01002 * Copyright (C) 2019 sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
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.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17*/
Kévin Redon69b92d92019-01-24 16:39:20 +010018
Harald Welte1b9a5b82019-02-24 23:04:45 +010019#include <stdlib.h>
Harald Welte5a8af4d2019-05-12 15:57:20 +020020#include <inttypes.h>
Harald Welte1b9a5b82019-02-24 23:04:45 +010021#include <stdio.h>
Kévin Redon072951b2019-05-02 15:17:46 +020022#include <math.h>
Harald Weltef53f2262019-02-24 11:01:08 +010023#include <parts.h>
Harald Welte65101be2019-04-18 18:30:49 +020024#include <errno.h>
Harald Weltec7a58ba2019-04-18 17:59:19 +020025
26#include <osmocom/core/utils.h>
Harald Welte458dc4b2019-11-12 06:47:11 +010027#include <osmocom/core/timer.h>
Harald Weltec7a58ba2019-04-18 17:59:19 +020028
Harald Weltef53f2262019-02-24 11:01:08 +010029#include <hal_cache.h>
Harald Welte93f628a2019-02-24 14:32:30 +010030#include <hri_port_e54.h>
Harald Weltef53f2262019-02-24 11:01:08 +010031
Kévin Redon69b92d92019-01-24 16:39:20 +010032#include "atmel_start.h"
33#include "atmel_start_pins.h"
Kévin Redon072951b2019-05-02 15:17:46 +020034#include "config/hpl_gclk_config.h"
Kévin Redon69b92d92019-01-24 16:39:20 +010035
Harald Weltec3f170d2019-02-24 09:06:59 +010036#include "i2c_bitbang.h"
37#include "octsim_i2c.h"
38#include "ncn8025.h"
Kévin Redon0f050722019-05-02 15:56:25 +020039#include "iso7816_3.h"
Harald Weltec3f170d2019-02-24 09:06:59 +010040
Harald Welteff9f4ce2019-02-24 22:51:09 +010041#include "command.h"
42
Eric Wildf5aa5892019-11-27 18:16:17 +010043#include "ccid_device.h"
44#include "usb_descriptors.h"
Harald Welte03d6ebb2019-09-28 23:19:31 +020045extern struct ccid_slot_ops iso_fsm_slot_ops;
46static struct ccid_instance g_ci;
Kévin Redonc89bb8c2019-04-17 01:20:23 +020047
Kévin Redon072951b2019-05-02 15:17:46 +020048
Harald Weltec7a58ba2019-04-18 17:59:19 +020049static void ccid_app_init(void);
50
Harald Weltec3f170d2019-02-24 09:06:59 +010051static void board_init()
52{
53 int i;
54
55 for (i = 0; i < 4; i++)
56 i2c_init(&i2c[i]);
57
Harald Welte255da5e2019-04-16 18:19:53 +020058 for (i = 0; i < 8; i++)
Harald Weltec3f170d2019-02-24 09:06:59 +010059 ncn8025_init(i);
Harald Weltef53f2262019-02-24 11:01:08 +010060
61 cache_init();
62 cache_enable(CMCC);
Harald Welted1bd5c42019-05-17 16:38:30 +020063 calendar_enable(&CALENDAR_0);
Harald Welte93f628a2019-02-24 14:32:30 +010064
65 /* increase drive strength of 20Mhz SIM clock output to 8mA
66 * (there are 8 inputs + traces to drive!) */
67 hri_port_set_PINCFG_DRVSTR_bit(PORT, 0, 11);
Kévin Redonc89bb8c2019-04-17 01:20:23 +020068
Harald Weltec7a58ba2019-04-18 17:59:19 +020069 ccid_app_init();
Harald Weltec3f170d2019-02-24 09:06:59 +010070}
71
Harald Weltec7a58ba2019-04-18 17:59:19 +020072/***********************************************************************
73 * CCID Driver integration
74 ***********************************************************************/
75
76#include <osmocom/core/linuxlist.h>
77#include <osmocom/core/msgb.h>
78#include "linuxlist_atomic.h"
79#include "ccid_df.h"
80
81struct usb_ep_q {
82 const char *name;
83 /* msgb queue of pending to-be-transmitted (IN/IRQ) or completed received (OUT)
84 * USB transfers */
85 struct llist_head list;
86 /* currently ongoing/processed msgb (USB transmit or receive */
87 struct msgb *in_progress;
88};
89
90struct ccid_state {
91 /* msgb queue of free msgs */
92 struct llist_head free_q;
93
94 /* msgb queue of pending to-be-transmitted (IN EP) */
95 struct usb_ep_q in_ep;
96 /* msgb queue of pending to-be-transmitted (IRQ EP) */
97 struct usb_ep_q irq_ep;
98 /* msgb queue of completed received (OUT EP) */
99 struct usb_ep_q out_ep;
Harald Welte5a8af4d2019-05-12 15:57:20 +0200100
101 /* bit-mask of card-insert status, as determined from NCN8025 IRQ output */
102 uint8_t card_insert_mask;
Harald Weltec7a58ba2019-04-18 17:59:19 +0200103};
Eric Wild3e859902019-11-27 18:34:39 +0100104static volatile struct ccid_state g_ccid_s;
Harald Weltec7a58ba2019-04-18 17:59:19 +0200105
106static void ccid_out_read_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred);
107static void ccid_in_write_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred);
108static void ccid_irq_write_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred);
109
110static void usb_ep_q_init(struct usb_ep_q *ep_q, const char *name)
111{
112 ep_q->name = name;
113 INIT_LLIST_HEAD(&ep_q->list);
114 ep_q->in_progress = NULL;
115}
116
117static void ccid_app_init(void)
118{
119 /* initialize data structures */
120 INIT_LLIST_HEAD(&g_ccid_s.free_q);
121 usb_ep_q_init(&g_ccid_s.in_ep, "IN");
122 usb_ep_q_init(&g_ccid_s.irq_ep, "IRQ");
123 usb_ep_q_init(&g_ccid_s.out_ep, "OUT");
124
125 /* OUT endpoint read complete callback (irq context) */
126 ccid_df_register_callback(CCID_DF_CB_READ_OUT, (FUNC_PTR)&ccid_out_read_compl);
127 /* IN endpoint write complete callback (irq context) */
128 ccid_df_register_callback(CCID_DF_CB_WRITE_IN, (FUNC_PTR)&ccid_in_write_compl);
129 /* IRQ endpoint write complete callback (irq context) */
130 ccid_df_register_callback(CCID_DF_CB_WRITE_IRQ, (FUNC_PTR)&ccid_irq_write_compl);
131}
132
133/* irqsafe version of msgb_enqueue */
134struct msgb *msgb_dequeue_irqsafe(struct llist_head *q)
135{
136 struct msgb *msg;
137 CRITICAL_SECTION_ENTER()
138 msg = msgb_dequeue(q);
139 CRITICAL_SECTION_LEAVE()
140 return msg;
141}
142
Harald Welte5a8af4d2019-05-12 15:57:20 +0200143void msgb_enqueue_irqsafe(struct llist_head *q, struct msgb *msg)
144{
145 CRITICAL_SECTION_ENTER()
146 msgb_enqueue(q, msg);
147 CRITICAL_SECTION_LEAVE()
148}
149
Harald Weltec7a58ba2019-04-18 17:59:19 +0200150/* submit the next pending (if any) message for the IN EP */
151static int submit_next_in(void)
152{
153 struct usb_ep_q *ep_q = &g_ccid_s.in_ep;
154 struct msgb *msg;
155 int rc;
156
Harald Welte03d6ebb2019-09-28 23:19:31 +0200157 if (ep_q->in_progress)
158 return 0;
159
Harald Weltec7a58ba2019-04-18 17:59:19 +0200160 msg = msgb_dequeue_irqsafe(&ep_q->list);
161 if (!msg)
162 return 0;
163
164 ep_q->in_progress = msg;
165 rc = ccid_df_write_in(msgb_data(msg), msgb_length(msg));
166 if (rc != ERR_NONE) {
167 printf("EP %s failed: %d\r\n", ep_q->name, rc);
168 return -1;
169 }
170 return 1;
171
172}
173
174/* submit the next pending (if any) message for the IRQ EP */
175static int submit_next_irq(void)
176{
177 struct usb_ep_q *ep_q = &g_ccid_s.irq_ep;
178 struct msgb *msg;
179 int rc;
180
Eric Wildeaafa9f2019-10-01 15:22:14 +0200181 if (ep_q->in_progress)
182 return 0;
183
Harald Weltec7a58ba2019-04-18 17:59:19 +0200184 msg = msgb_dequeue_irqsafe(&ep_q->list);
185 if (!msg)
186 return 0;
187
188 ep_q->in_progress = msg;
189 rc = ccid_df_write_irq(msgb_data(msg), msgb_length(msg));
190 /* may return HALTED/ERROR/DISABLED/BUSY/ERR_PARAM/ERR_FUNC/ERR_DENIED */
191 if (rc != ERR_NONE) {
192 printf("EP %s failed: %d\r\n", ep_q->name, rc);
193 return -1;
194 }
195 return 1;
196}
197
198static int submit_next_out(void)
199{
200 struct usb_ep_q *ep_q = &g_ccid_s.out_ep;
201 struct msgb *msg;
202 int rc;
203
204 OSMO_ASSERT(!ep_q->in_progress);
205 msg = msgb_dequeue_irqsafe(&g_ccid_s.free_q);
206 if (!msg)
207 return -1;
Harald Welte03d6ebb2019-09-28 23:19:31 +0200208 msgb_reset(msg);
Harald Weltec7a58ba2019-04-18 17:59:19 +0200209 ep_q->in_progress = msg;
210
211 rc = ccid_df_read_out(msgb_data(msg), msgb_tailroom(msg));
212 if (rc != ERR_NONE) {
213 /* re-add to the list of free msgb's */
214 llist_add_tail_at(&g_ccid_s.free_q, &msg->list);
215 return 0;
216 }
217 return 1;
218}
219
220/* OUT endpoint read complete callback (irq context) */
221static void ccid_out_read_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred)
222{
223 struct msgb *msg = g_ccid_s.out_ep.in_progress;
224
225 /* add just-received msg to tail of endpoint queue */
226 OSMO_ASSERT(msg);
227 /* update msgb with the amount of data received */
228 msgb_put(msg, transferred);
229 /* append to list of pending-to-be-handed messages */
230 llist_add_tail_at(&msg->list, &g_ccid_s.out_ep.list);
Harald Welte03d6ebb2019-09-28 23:19:31 +0200231 g_ccid_s.out_ep.in_progress = NULL;
Harald Weltec7a58ba2019-04-18 17:59:19 +0200232
233 /* submit another [free] msgb to receive the next transfer */
234 submit_next_out();
235}
236
237/* IN endpoint write complete callback (irq context) */
238static void ccid_in_write_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred)
239{
240 struct msgb *msg = g_ccid_s.in_ep.in_progress;
241
242 OSMO_ASSERT(msg);
243 /* return the message back to the queue of free message buffers */
244 llist_add_tail_at(&msg->list, &g_ccid_s.free_q);
245 g_ccid_s.in_ep.in_progress = NULL;
246
247 /* submit the next pending to-be-transmitted msgb (if any) */
248 submit_next_in();
249}
250
251/* IRQ endpoint write complete callback (irq context) */
252static void ccid_irq_write_compl(const uint8_t ep, enum usb_xfer_code code, uint32_t transferred)
253{
254 struct msgb *msg = g_ccid_s.irq_ep.in_progress;
255
256 OSMO_ASSERT(msg);
257 /* return the message back to the queue of free message buffers */
258 llist_add_tail_at(&msg->list, &g_ccid_s.free_q);
259 g_ccid_s.irq_ep.in_progress = NULL;
260
261 /* submit the next pending to-be-transmitted msgb (if any) */
262 submit_next_irq();
263}
264
Harald Welte5a8af4d2019-05-12 15:57:20 +0200265#include "ccid_proto.h"
Eric Wild2de998a2019-10-01 15:20:32 +0200266static struct msgb *ccid_gen_notify_slot_status(uint8_t old_bm, uint8_t new_bm)
Harald Welte5a8af4d2019-05-12 15:57:20 +0200267{
Eric Wild2de998a2019-10-01 15:20:32 +0200268 uint8_t statusbytes[2] = {0};
Harald Welte5a8af4d2019-05-12 15:57:20 +0200269 //struct msgb *msg = ccid_msgb_alloc();
Eric Wild759a6462019-11-11 14:22:52 +0100270 struct msgb *msg = msgb_alloc(300,"IRQ");
Eric Wild2de998a2019-10-01 15:20:32 +0200271 struct ccid_rdr_to_pc_notify_slot_change *nsc = msgb_put(msg, sizeof(*nsc) + sizeof(statusbytes));
Harald Welte5a8af4d2019-05-12 15:57:20 +0200272 nsc->bMessageType = RDR_to_PC_NotifySlotChange;
Eric Wild2de998a2019-10-01 15:20:32 +0200273
274 for(int i = 0; i <8; i++) {
275 uint8_t byteidx = i >> 2;
Eric Wild20a83682019-11-26 17:57:06 +0100276 uint8_t old_bit = (old_bm >> i) & 1;
277 uint8_t new_bit = (new_bm >> i) & 1;
Eric Wild2de998a2019-10-01 15:20:32 +0200278 uint8_t bv;
279 if (old_bit == new_bit && new_bit == 0)
280 bv = 0x00;
281 else if (old_bit == new_bit && new_bit == 1)
282 bv = 0x01;
283 else if (old_bit != new_bit && new_bit == 0)
284 bv = 0x02;
285 else
286 bv = 0x03;
287
288 statusbytes[byteidx] |= bv << ((i % 4) << 1);
289 }
290
291 memcpy(&nsc->bmSlotCCState, statusbytes, sizeof(statusbytes));
Harald Welte5a8af4d2019-05-12 15:57:20 +0200292
293 return msg;
294}
295
296/* check if any card detect state has changed */
297static void poll_card_detect(void)
298{
299 uint8_t new_mask = 0;
300 struct msgb *msg;
301 unsigned int i;
302
Harald Welte03d6ebb2019-09-28 23:19:31 +0200303 for (i = 0; i < 8; i++){
304 bool level = ncn8025_interrupt_level(i);
305 new_mask |= level << i;
Eric Wild9e622dc2019-11-27 14:43:16 +0100306 g_ci.slot_ops->icc_set_insertion_status(&g_ci.slot[i], level);
Harald Welte03d6ebb2019-09-28 23:19:31 +0200307 }
Harald Welte5a8af4d2019-05-12 15:57:20 +0200308
309 /* notify the user/host about any changes */
310 if (g_ccid_s.card_insert_mask != new_mask) {
311 printf("CARD_DET 0x%02x -> 0x%02x\r\n",
312 g_ccid_s.card_insert_mask, new_mask);
Eric Wild2de998a2019-10-01 15:20:32 +0200313 msg = ccid_gen_notify_slot_status(g_ccid_s.card_insert_mask, new_mask);
Harald Welte5a8af4d2019-05-12 15:57:20 +0200314 msgb_enqueue_irqsafe(&g_ccid_s.irq_ep.list, msg);
315
316 g_ccid_s.card_insert_mask = new_mask;
317 }
318}
319
320
Harald Weltec7a58ba2019-04-18 17:59:19 +0200321
322/***********************************************************************
323 * Command Line interface
324 ***********************************************************************/
325
Harald Welte2dc67e92019-05-17 18:01:46 +0200326
Harald Welte67b2aba2019-04-16 20:47:22 +0200327extern void testmode_init(void);
Harald Weltebdf1b352019-05-17 10:21:45 +0200328extern void libosmo_emb_init(void);
Harald Welte1017a752019-05-17 20:39:49 +0200329extern void libosmo_emb_mainloop(void);
Harald Welte1b9a5b82019-02-24 23:04:45 +0100330
Harald Welte8049d662019-04-17 21:19:18 +0200331#include "talloc.h"
Harald Weltebdf1b352019-05-17 10:21:45 +0200332#include "logging.h"
Harald Welte03d6ebb2019-09-28 23:19:31 +0200333
Harald Welte8049d662019-04-17 21:19:18 +0200334void *g_tall_ctx;
335
Harald Welte8049d662019-04-17 21:19:18 +0200336
Harald Welte65101be2019-04-18 18:30:49 +0200337/* Section 9.6 of SAMD5x/E5x Family Data Sheet */
338static int get_chip_unique_serial(uint8_t *out, size_t len)
339{
340 uint32_t *out32 = (uint32_t *)out;
341 if (len < 16)
342 return -EINVAL;
343
344 out32[0] = *(uint32_t *)0x008061fc;
345 out32[1] = *(uint32_t *)0x00806010;
346 out32[2] = *(uint32_t *)0x00806014;
347 out32[3] = *(uint32_t *)0x00806018;
348
349 return 0;
350}
351
352/* same as get_chip_unique_serial but in hex-string format */
353static int get_chip_unique_serial_str(char *out, size_t len)
354{
355 uint8_t buf[16];
356 int rc;
357
358 if (len < 16*2 + 1)
359 return -EINVAL;
360
361 rc = get_chip_unique_serial(buf, sizeof(buf));
362 if (rc < 0)
363 return rc;
364 osmo_hexdump_buf(out, len, buf, sizeof(buf), NULL, false);
365 return 0;
366}
367
Harald Welte9ab4bc82019-05-17 18:36:01 +0200368#define RSTCAUSE_STR_SIZE 64
369static void get_rstcause_str(char *out)
370{
371 uint8_t val = hri_rstc_read_RCAUSE_reg(RSTC);
372 *out = '\0';
373 if (val & RSTC_RCAUSE_POR)
374 strcat(out, "POR ");
375 if (val & RSTC_RCAUSE_BODCORE)
376 strcat(out, "BODCORE ");
377 if (val & RSTC_RCAUSE_BODVDD)
378 strcat(out, "BODVDD ");
379 if (val & RSTC_RCAUSE_NVM)
380 strcat(out, "NVM ");
381 if (val & RSTC_RCAUSE_EXT)
382 strcat(out, "EXT ");
383 if (val & RSTC_RCAUSE_WDT)
384 strcat(out, "WDT ");
385 if (val & RSTC_RCAUSE_SYST)
386 strcat(out, "SYST ");
387 if (val & RSTC_RCAUSE_BACKUP)
388 strcat(out, "BACKUP ");
389}
390
Harald Welte03d6ebb2019-09-28 23:19:31 +0200391//#######################
392
393
394
395static uint32_t clock_freqs[] = {
396 2500000
397};
398
399static uint32_t data_rates[] = {
400 6720
401};
402extern struct usb_desc_collection usb_fs_descs;
403
404
405
406static int feed_ccid(void)
407{
408 struct usb_ep_q *ep_q = &g_ccid_s.out_ep;
409 struct msgb *msg;
410 int rc;
411
412 msg = msgb_dequeue_irqsafe(&g_ccid_s.out_ep.list);
413 if (!msg)
414 return -1;
415
416 ccid_handle_out(&g_ci, msg);
417 return 1;
418}
419
420static int ccid_ops_send_in(struct ccid_instance *ci, struct msgb *msg)
421{
422 /* add just-received msg to tail of endpoint queue */
423 OSMO_ASSERT(msg);
424
425 /* append to list of pending-to-be-handed messages */
426 llist_add_tail_at(&msg->list, &g_ccid_s.in_ep.list);
427 submit_next_in();
428 return 0;
429}
430
431static const struct ccid_ops c_ops = {
432 .send_in = ccid_ops_send_in,
433 .send_int = 0,
434};
435
436//#######################
437
Eric Wild22887032019-11-27 18:10:39 +0100438#define NUM_OUT_BUF 16
Harald Welte03d6ebb2019-09-28 23:19:31 +0200439
Kévin Redon69b92d92019-01-24 16:39:20 +0100440int main(void)
441{
Harald Welte65101be2019-04-18 18:30:49 +0200442 char sernr_buf[16*2+1];
Harald Welte9ab4bc82019-05-17 18:36:01 +0200443 char rstcause_buf[RSTCAUSE_STR_SIZE];
Harald Welte65101be2019-04-18 18:30:49 +0200444
Eric Wild9b3fe272019-11-27 18:26:08 +0100445#if 0
446CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk ; //| /* tracing*/
447////CoreDebug_DEMCR_MON_EN_Msk; /* mon interupt catcher */
448
449
450DWT->COMP0 = 0x40003028; /* sercom 0 data */
451//DWT->COMP0 = 0x40003428; /* sercom 1 data */
452DWT->MASK0 = 0; /* 0 */
453DWT->FUNCTION0 = 0; /* has to be 0 for linked address */
454
455DWT->COMP1 = 0xa5; /* value */
456DWT->MASK1 = 0; /* match all bits */
457DWT->FUNCTION1 = (0b10 << DWT_FUNCTION_DATAVSIZE_Pos) | /* DATAVSIZE 10 - dword */
458#if 1
459(0 << DWT_FUNCTION_DATAVADDR0_Pos) | /* Data Match linked addr pointer in COMP0 */
460#else
461(1 << DWT_FUNCTION_DATAVADDR0_Pos) | /* Data Match on any addr -> own number */
462#endif
463(1 << DWT_FUNCTION_DATAVMATCH_Pos) | /* DATAVMATCH Enable data comparation */
464(0b0111 << DWT_FUNCTION_FUNCTION_Pos); /* generate a watchpoint event on rw */
465
466#endif
467
Kévin Redon69b92d92019-01-24 16:39:20 +0100468 atmel_start_init();
Harald Welte65101be2019-04-18 18:30:49 +0200469 get_chip_unique_serial_str(sernr_buf, sizeof(sernr_buf));
Harald Welte9ab4bc82019-05-17 18:36:01 +0200470 get_rstcause_str(rstcause_buf);
Kévin Redon78d2f442019-01-24 18:45:59 +0100471
Kévin Redon8e538002019-01-30 11:19:19 +0100472 usb_start();
473
Harald Weltec3f170d2019-02-24 09:06:59 +0100474 board_init();
Harald Welteff9f4ce2019-02-24 22:51:09 +0100475 command_init("sysmoOCTSIM> ");
Harald Weltec3f170d2019-02-24 09:06:59 +0100476
Eric Wild5de00c22019-11-27 19:10:09 +0100477 /* boost uart priority by setting all other irqs to uartprio+1 */
478 for(int i = 0; i < PERIPH_COUNT_IRQn; i++)
479 NVIC_SetPriority(i, 2);
480 for(int i = SERCOM0_0_IRQn; i <= SERCOM7_3_IRQn; i++)
481 NVIC_SetPriority(i, 1);
482
Harald Welte729a7622019-05-17 11:02:11 +0200483 printf("\r\n\r\n"
484 "=============================================================================\n\r"
485 "sysmoOCTSIM firmware " GIT_VERSION "\n\r"
486 "(C) 2018-2019 by sysmocom - s.f.m.c. GmbH and contributors\n\r"
487 "=============================================================================\n\r");
488 printf("Chip ID: %s\r\n", sernr_buf);
Harald Welte9ab4bc82019-05-17 18:36:01 +0200489 printf("Reset cause: %s\r\n", rstcause_buf);
Harald Weltee7aa5342019-04-16 21:11:14 +0200490
Harald Welte8049d662019-04-17 21:19:18 +0200491 talloc_enable_null_tracking();
492 g_tall_ctx = talloc_named_const(NULL, 0, "global");
493 printf("g_tall_ctx=%p\r\n", g_tall_ctx);
Harald Weltebdf1b352019-05-17 10:21:45 +0200494
Eric Wild27f60452019-11-27 18:04:39 +0100495 //FIXME osmo_emb has a pool?
496 msgb_talloc_ctx_init(g_tall_ctx, 0);
497
Harald Weltebdf1b352019-05-17 10:21:45 +0200498 libosmo_emb_init();
499
500 LOGP(DUSB, LOGL_ERROR, "foobar usb\n");
Harald Welte8049d662019-04-17 21:19:18 +0200501
Eric Wildda142a02019-11-27 18:05:22 +0100502 //prevent spurious interrupts before our driver structs are ready
503 CRITICAL_SECTION_ENTER()
Harald Welte03d6ebb2019-09-28 23:19:31 +0200504 ccid_instance_init(&g_ci, &c_ops, &iso_fsm_slot_ops, &usb_fs_descs.ccid.class,
505 data_rates, clock_freqs, "", 0);
506
507 for(int i =0; i < NUM_OUT_BUF; i++){
508 struct msgb *msg = msgb_alloc(300, "ccid");
509 OSMO_ASSERT(msg);
510 /* return the message back to the queue of free message buffers */
511 llist_add_tail_at(&msg->list, &g_ccid_s.free_q);
512 }
513 submit_next_out();
Eric Wildda142a02019-11-27 18:05:22 +0100514 CRITICAL_SECTION_LEAVE()
Eric Wild9a2279c2019-11-27 18:30:18 +0100515#if 0
516 /* CAN_RX */
517 gpio_set_pin_function(PIN_PB12, GPIO_PIN_FUNCTION_OFF);
518 gpio_set_pin_direction(PIN_PB12, GPIO_DIRECTION_OUT);
519 gpio_set_pin_level(PIN_PB12, false);
520
521 /* CAN_TX */
522 gpio_set_pin_function(PIN_PB13, GPIO_PIN_FUNCTION_OFF);
523 gpio_set_pin_direction(PIN_PB13, GPIO_DIRECTION_OUT);
524 gpio_set_pin_level(PIN_PB13, false);
525#endif
Harald Welte03d6ebb2019-09-28 23:19:31 +0200526
527// command_print_prompt();
Kévin Redon8e538002019-01-30 11:19:19 +0100528 while (true) { // main loop
Harald Welteff9f4ce2019-02-24 22:51:09 +0100529 command_try_recv();
Harald Welte5a8af4d2019-05-12 15:57:20 +0200530 poll_card_detect();
Eric Wildeaafa9f2019-10-01 15:22:14 +0200531 submit_next_irq();
Eric Wild22887032019-11-27 18:10:39 +0100532 for (int i = 0; i <= usb_fs_descs.ccid.class.bMaxSlotIndex; i++){
Eric Wild759a6462019-11-11 14:22:52 +0100533 g_ci.slot_ops->handle_fsm_events(&g_ci.slot[i], true);
534 }
Harald Welte03d6ebb2019-09-28 23:19:31 +0200535 feed_ccid();
Harald Welte1017a752019-05-17 20:39:49 +0200536 osmo_timers_update();
Harald Welte03d6ebb2019-09-28 23:19:31 +0200537 int qs = llist_count_at(&g_ccid_s.free_q);
538 if(qs > NUM_OUT_BUF)
539 for (int i= 0; i < qs-NUM_OUT_BUF; i++){
540 struct msgb *msg = msgb_dequeue_irqsafe(&g_ccid_s.free_q);
541 if (msg)
542 msgb_free(msg);
543 }
544 if(qs < NUM_OUT_BUF)
Eric Wild759a6462019-11-11 14:22:52 +0100545 for (int i= 0; i < NUM_OUT_BUF-qs; i++){
Harald Welte03d6ebb2019-09-28 23:19:31 +0200546 struct msgb *msg = msgb_alloc(300,"ccid");
547 OSMO_ASSERT(msg);
548 /* return the message back to the queue of free message buffers */
549 llist_add_tail_at(&msg->list, &g_ccid_s.free_q);
550 }
551
Kévin Redon8e538002019-01-30 11:19:19 +0100552 }
Kévin Redon69b92d92019-01-24 16:39:20 +0100553}