1 #include <libfb/fb_lib.h>
2 #include <libfb/fblib_ver.h>
3 #ifdef HAVE_STDLIB_H
4 # include <stdlib.h>
5 #endif
6
7 #ifdef HAVE_UNISTD_H
8 # include <unistd.h>
9 #endif
10
11 #ifdef HAVE_TIME_H
12 # include <time.h>
13 #endif
14
15 /** @file fb_lib.c
16 * @author Brett Carrington
17 *
18 * @brief Most general library functions and all UDP transmission and
19 * reception functions
20 *
21 *
22 * @mainpage The foneBRIDGE library
23 *
24 * The libfb library provides a comprehensive package for configuring
25 * and querying foneBRIDGE-based hardware devices over UDP and raw
26 * Ethernet. The library tracks the context of individual devices and
27 * handles all connections and data transmission using libnet and
28 * libpcap.
29 *
30 * The library is reentrant in the sense that different context
31 * pointers (devices) cannot effect each other. Each device must
32 * obtain a unique context using libfb_init() and then a connection to
33 * the device must be established with libfb_connect(). Multiple
34 * contexts to the same device produced undefined behavior.
35 *
36 */
37
38 /************ Prototypes and Constants ***************/
39 static int set_filter (libfb_t * f, bpf_u_int32 mask);
40
41 /** Valid configuations for longhaul LBOs*/
42 const unsigned char longlbo[MAX_LONGLBO] = {
43 PULS_LBO0,
44 PULS_LBO1,
45 PULS_LBO2,
46 PULS_LBO3
47 };
48
49 /** Valid configuations for shorthaul LBOs*/
50 const unsigned char shortlbo[MAX_SHORTLBO] = {
51 PULS_133,
52 PULS_266,
53 PULS_399,
54 PULS_533,
55 PULS_655
56 };
57
58 /** Table of libfb error strings */
59 const char *fberrstr[] = {
60 "Success",
61 "Try Again (Would Block)",
62 "Timed Out",
63 "Check System Errno",
64 "Invalid Argument",
65 "Invalid Bytecount",
66 "Exceeded System Maximum or Limit"
67 };
68
69 /** Table of DOOF error strings (from the device) */
70 const char *dooferrstr[] = {
71 "Success",
72 "Failed CRC",
73 "No Memory Available",
74 "Invalid Command",
75 "Out of Bounds",
76 "No Device Present",
77 "Bad Packet Length",
78 "Bad Parameter"
79 };
80
81 /************ Setup Functions ***************/
82
83 /** @brief Print version information to stdout */
84 void
libfb_printver()85 libfb_printver ()
86 {
87 printf ("libfb Version %s, Build %d\n", FBLIB_VER, FBLIB_BUILD_NUM);
88 }
89
90 /** @brief Library initalization routine
91 *
92 * This sets up the library to begin operation with a device. It
93 * returns the context pointer needed for almost all operations.
94 *
95 * @param device the name of the ethernet device if raw ethernet is used, otherwise NULL
96 * @param ethernet one of LIBFB_ETHERNET_OFF or LIBFB_ETHERNET_ON
97 * @param errstr A buffer of at least length LIBFB_ERRBUF_SIZE to store an error message
98 * @return The initalized context pointer, or NULL is an error occurs
99 */
100 libfb_t *
libfb_init(char * device,int ethernet,char * errstr)101 libfb_init (char *device, int ethernet, char *errstr)
102 {
103 libfb_t *f;
104
105 bpf_u_int32 mask; /* The netmask of our sniffing device */
106 bpf_u_int32 net; /* The IP of our sniffing device */
107
108 f = malloc (sizeof (libfb_t));
109 if (f == NULL)
110 {
111 strncpy (errstr, "Fatal error, could not allocate memory!\n",
112 LIBFB_ERRBUF_SIZE);
113 return NULL;
114 }
115
116 memset (f, 0, sizeof (libfb_t));
117
118 f->udp_socket = -1;
119
120 if ((f->ether_on = ethernet) == LIBFB_ETHERNET_ON)
121 {
122
123 if (device == NULL)
124 {
125 strncpy (errstr, "Fatal error, no device specified!\n",
126 LIBFB_ERRBUF_SIZE);
127 goto init_error_out_1;
128
129 }
130
131 f->s_mac = get_local_mac (device);
132 if (f->s_mac == NULL)
133 {
134 strncpy (errstr, "Unable to lookup local MAC address!\n",
135 LIBFB_ERRBUF_SIZE);
136 goto init_error_out_1;
137 }
138
139 f->l = libnet_init (LIBNET_LINK, device, errstr);
140 if (f->l == NULL)
141 goto init_error_out_2; /* libnet/libpcap will fill out errstr from here on in */
142
143 /* look up netmask */
144 if (pcap_lookupnet (device, &net, &mask, errstr) == -1)
145 {
146 fprintf (stderr,
147 "[Warning] Can't get netmask for device %s\n", device);
148 net = 0;
149 mask = 0;
150 }
151
152 /* open pcap */
153 f->p = pcap_open_live (device, 512, 0, 0, errstr);
154 if (f->p == NULL)
155 goto init_error_out_3;
156
157 /* set up pcap filter */
158 if (set_filter (f, mask) == -1)
159 {
160 strncpy (errstr, pcap_geterr (f->p), LIBFB_ERRBUF_SIZE);
161 goto init_error_out_4;
162 }
163 } /* end of ethernet enabling functions */
164
165 f->crc_en = 0;
166 f->device = device;
167 return f;
168
169 /* Error handling, free up things we've allocated */
170 init_error_out_4:
171 pcap_close (f->p);
172 init_error_out_3:
173 libnet_destroy (f->l);
174 init_error_out_2:
175 free (f->s_mac);
176 init_error_out_1:
177 free (f);
178 return NULL;
179 }
180
181
182 /** @brief Connect to a device via UDP sockets
183 *
184 * This is usually the first operation done after obtaining the
185 * context pointer with libfb_init. Communication with the device via
186 * UDP is not possible until this connection is established.
187 *
188 * @param f the device context pointer
189 * @param host null-terminated string representing the hostname (or IP address) of the device
190 * @param port the UDP port to use, historically 1024 has been used for foneBRIDGE-type devices
191 * @return an fblib_err error code, or FBLIB_ESUCCESS if successfully connected
192 */
193 fblib_err
libfb_connect(libfb_t * f,const char * host,int port)194 libfb_connect (libfb_t * f, const char *host, int port)
195 {
196 struct hostent *hostPtr = NULL;
197 struct sockaddr_in dSock = { 0 };
198
199 f->udp_socket = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
200 if (f->udp_socket == -1)
201 return FBLIB_EERRNO;
202
203 hostPtr = gethostbyname (host);
204 if (hostPtr == NULL)
205 {
206 hostPtr = gethostbyaddr (host, strlen (host), AF_INET);
207 if (hostPtr == NULL)
208 return FBLIB_EHERRNO;
209 }
210
211 dSock.sin_family = AF_INET;
212 dSock.sin_port = htons (port);
213 memcpy (&dSock.sin_addr, hostPtr->h_addr, hostPtr->h_length);
214
215 if ((connect (f->udp_socket, (struct sockaddr *) &dSock, sizeof (dSock))) ==
216 -1)
217 return FBLIB_EERRNO;
218
219 f->connected = 1;
220 return FBLIB_ESUCCESS;
221 }
222
223 /** \brief Internal function to set up libpcap filter for 0xD00F packets
224 *
225 * \param f must be a libfb_t context with a valid pcap context
226 * \param mask the netmask on the interface the context operates on
227 * \return 0 on success, -1 if a failure occured
228 */
229 static int
set_filter(libfb_t * f,bpf_u_int32 mask)230 set_filter (libfb_t * f, bpf_u_int32 mask)
231 {
232 struct bpf_program filter;
233 char m_str[] = "00:00:00:00:00:00";
234 char filterstr[128];
235
236 strcpy (filterstr, "ether proto 0xd00f and ether dst ");
237 sprintf (m_str, "%02X:%02X:%02X:%02X:%02X:%02X",
238 f->s_mac[0], f->s_mac[1], f->s_mac[2],
239 f->s_mac[3], f->s_mac[4], f->s_mac[5]);
240
241 if (pcap_compile (f->p, &filter, strcat (filterstr, m_str), 0, mask) == -1)
242 return -1;
243
244 if (pcap_setfilter (f->p, &filter) == -1)
245 return -1;
246
247 return 0;
248 }
249
250
251 /** @brief Set reference times for printing date information
252 *
253 * This must be called before the libfb_get-ctime and
254 * libfb_get_systime functions are used.
255 *
256 * @param f the device context
257 */
258 void
set_reftime(libfb_t * f)259 set_reftime (libfb_t * f)
260 {
261 struct tm time_info;
262
263 /* Set ref. time to Jan 1st 2000 */
264 memset (&time_info, 0, sizeof (struct tm));
265 time_info.tm_mday = 1;
266 time_info.tm_mon = 0;
267 time_info.tm_year = 100;
268 f->ref_ctime = mktime (&time_info);
269
270 /* Set the reference for the SYSID timestamp */
271 time_info.tm_year = 70;
272 f->sysid_ctime = mktime (&time_info);
273 }
274
275 /**
276 * @brief Get the flash date information
277 * @param f the device context
278 * @return the flash date
279 */
280 inline time_t
libfb_get_ctime(libfb_t * f)281 libfb_get_ctime (libfb_t * f)
282 {
283 return f->ref_ctime;
284 }
285
286 /**
287 * @brief get the sysid time stamp
288 * @param f the device context
289 * @return the sysid time stamp
290 */
291 inline time_t
libfb_get_systime(libfb_t * f)292 libfb_get_systime (libfb_t * f)
293 {
294 return f->sysid_ctime;
295 }
296
297 /************ Shutdown Functions ***************/
298
299 /** @brief free resources used by the library
300 *
301 * @param f the context owning the resources
302 * @return always succeeds with FBLIB_ESUCCESS
303 */
304 fblib_err
libfb_destroy(libfb_t * f)305 libfb_destroy (libfb_t * f)
306 {
307 if (f)
308 {
309 if (f->connected)
310 close (f->udp_socket);
311
312 if (f->p)
313 pcap_close (f->p);
314
315 if (f->l)
316 libnet_destroy (f->l);
317
318 if (f->s_mac)
319 free (f->s_mac);
320
321 free (f);
322 }
323
324 return FBLIB_ESUCCESS;
325 }
326
327
328
329 /************ FB Query Functions ***************/
330 /** @brief print the device static information to stream
331 *
332 * @param f the device context
333 * @param stream the output stream (i.e. stdout, stderr...)
334 * @param packet_in the DOOF_STATIC_INFO data structure containing the information to display
335 */
336 void
fprint_static_info(libfb_t * f,FILE * stream,DOOF_STATIC_INFO * packet_in)337 fprint_static_info (libfb_t * f, FILE * stream, DOOF_STATIC_INFO * packet_in)
338 {
339 struct tm *time_info = malloc (sizeof (struct tm));
340 time_t calendar_time;
341 int x;
342
343 set_reftime (f);
344
345 fprintf (stream, "SW ver: %s\n", packet_in->sw_ver);
346 fprintf (stream, "SW Compile date: %s\n", packet_in->sw_compile_date);
347 fprintf (stream, "Build number: %d\n", packet_in->build_num);
348 fprintf (stream, "FB core ver sig: 0x%X\n", packet_in->fb_core_version);
349 fprintf (stream, "Spans: %d Devices: %d MACs: %d\n", packet_in->spans,
350 packet_in->devices, packet_in->mac_num);
351 fprintf (stream, "EPCS Blocks: %d\n", packet_in->epcs_blocks);
352 fprintf (stream, "EPCS Block size: 0x%X (%d KB)\n",
353 packet_in->epcs_block_size, packet_in->epcs_block_size / 1024);
354 fprintf (stream, "EPCS Region size: 0x%X (%d KB)\n",
355 packet_in->epcs_region_size, packet_in->epcs_region_size / 1024);
356 fprintf (stream, "\nStored config data:\n");
357 fprintf (stream, "--------------------\n");
358 for (x=0; x<packet_in->mac_num; x++) {
359 fprintf (stream, "MAC[%d]: ", x);
360 fprint_mac (stream, packet_in->epcs_config.mac_addr);
361 packet_in->epcs_config.mac_addr[5]++;
362 fprintf (stream, "IP[%d]: ", x);
363 fprint_ip (stream, packet_in->epcs_config.ip_address[x]);
364 }
365 fprintf (stream, "Serial: %s\n", packet_in->epcs_config.snumber);
366 fprintf (stream, "CFG Flags: 0x%X (%s)\n",
367 packet_in->epcs_config.cfg_flags,
368 packet_in->epcs_config.cfg_flags & (1 << 0) ? "IEC" : "FB2");
369 calendar_time = packet_in->epcs_config.mfg_date + libfb_get_ctime (f);
370 time_info = localtime (&calendar_time);
371 fprintf (stream, "Flash Date: %d (%d/%d/%d %d:%d:%d)\n",
372 (int) calendar_time, time_info->tm_mon + 1, time_info->tm_mday,
373 time_info->tm_year + 1900, time_info->tm_hour, time_info->tm_min,
374 time_info->tm_sec);
375 fprintf (stream, "CRC: 0x%X\n", packet_in->epcs_config.crc16);
376 fprintf (stream, "SYSID CRC: 0x%X\n", packet_in->fpga_sysid);
377 calendar_time = packet_in->fpga_timestamp + libfb_get_systime (f);
378
379 time_info = localtime (&calendar_time);
380 fprintf (stream, "SYSID Timestamp: 0x%X (%d/%d/%d %d:%d:%d)\n",
381 packet_in->fpga_timestamp,
382 time_info->tm_mon + 1, time_info->tm_mday,
383 time_info->tm_year + 1900, time_info->tm_hour, time_info->tm_min,
384 time_info->tm_sec);
385 fprintf (stream, "Attempted boots: %d\n",
386 packet_in->epcs_config.attempted_boots);
387 fprintf (stream, "GPAK File Length: %d bytes\n",
388 packet_in->epcs_config.gpak_len);
389 fprintf (stream, "\nDSP Parameters\n-----------------\n");
390 fprintf (stream, "Active/Max channels: %d/%d\n",
391 packet_in->gpak_config.active_channels,
392 packet_in->gpak_config.max_channels);
393 fprintf (stream, "BIST: %d Num EC: %d\n", packet_in->gpak_config.bist,
394 packet_in->gpak_config.num_ec);
395 fprintf (stream, "Stream0: Max channels: %d Supported channels: %d\n",
396 packet_in->gpak_config.stream_slots[0],
397 packet_in->gpak_config.stream_supported_slots[0]);
398 fprintf (stream, "Stream1: Max channels: %d Supported channels: %d\n",
399 packet_in->gpak_config.stream_slots[1],
400 packet_in->gpak_config.stream_supported_slots[1]);
401 fprintf (stream, "GPAK VerID: 0x%X\n", packet_in->gpak_config.ver);
402 }
403
404 /** @brief print the device static information to stdout
405 *
406 * @param f the device context
407 * @param packet_in the DOOF_STATIC_INFO data structure containing the information to display
408 */
409 void
print_static_info(libfb_t * f,DOOF_STATIC_INFO * packet_in)410 print_static_info (libfb_t * f, DOOF_STATIC_INFO * packet_in)
411 {
412 fprint_static_info (f, stdout, packet_in);
413 }
414
415 /** @brief get the DOOF_STATIC_INFO information from a device using raw Ethernet
416 *
417 * @param f the device context
418 * @param dest_mac the destination MAC address
419 * @param doof_info pointer to location to store the DOOF_STATIC_INFO
420 * @return returns the length of the DOOF response
421 */
422 int
get_static_info(libfb_t * f,unsigned char * dest_mac,DOOF_STATIC_INFO * doof_info)423 get_static_info (libfb_t * f, unsigned char *dest_mac,
424 DOOF_STATIC_INFO * doof_info)
425 {
426 return get_epcs_pointer (f, dest_mac, doof_info);
427 }
428
429 /** @brief workhorse function for get_static_info
430 *
431 * @param f the device context
432 * @param dest_mac the destination MAC address
433 * @param ptr pointer to a buffer to store the DOOF_STATIC_INFO in
434 * @return returns the length of the DOOF response
435 */
436 int
get_epcs_pointer(libfb_t * f,unsigned char * dest_mac,DOOF_STATIC_INFO * ptr)437 get_epcs_pointer (libfb_t * f, unsigned char *dest_mac,
438 DOOF_STATIC_INFO * ptr)
439 {
440 int res;
441 unsigned char recv_buf[1500];
442
443 res =
444 doof_txrx (f, dest_mac, NULL, DOOF_CMD_GET_STATIC_INFO, 0, 0, recv_buf);
445
446 if (res < 0)
447 return res;
448
449 if (res != sizeof (DOOF_STATIC_INFO))
450 {
451 printf ("get_static_info: Incorrent byte-length received (%d)\n", res);
452 return -DOOF_RESP_BADSIZE;
453 }
454
455
456 memcpy ((unsigned char *) ptr, recv_buf + DOOF_PL_OFF + 14,
457 sizeof (DOOF_STATIC_INFO));
458
459 return 0;
460 }
461
462 /************ End FB Query Functions ***********/
463
464 /********************** UDP Functions *******************/
465 /** @brief the modern way to get the DOOF_STATIC_INFO information
466 *
467 * @param f the device context
468 * @param dsi location to store the DOOF_STATIC_INFO information in
469 * @return an fblib_err representing success or failure
470 */
471 fblib_err
udp_get_static_info(libfb_t * f,DOOF_STATIC_INFO * dsi)472 udp_get_static_info (libfb_t * f, DOOF_STATIC_INFO * dsi)
473 {
474 unsigned char buffer[1500];
475 ssize_t status;
476 fblib_err ret;
477 /* getinfo */
478 buffer[0] = 0;
479 buffer[1] = DOOF_CMD_GET_STATIC_INFO;
480
481 /* write packet */
482 if (!udp_ready_write (f))
483 return FBLIB_EAGAIN;
484
485 status = write (f->udp_socket, buffer, 2);
486 if (status == -1)
487 return FBLIB_EERRNO;
488
489 /* read back */
490 ret = poll_for_newpkt (f);
491 if (ret != FBLIB_ESUCCESS)
492 return ret;
493
494 status = read (f->udp_socket, buffer, sizeof (buffer));
495
496 /* Check length */
497 if (status != (2 + sizeof (DOOF_STATIC_INFO)))
498 {
499 return -DOOF_RESP_BADSIZE;
500 }
501 /* Length is correct */
502 memcpy ((void *) dsi, buffer + 2, sizeof (DOOF_STATIC_INFO));
503
504 return FBLIB_ESUCCESS;
505 }
506
507 /** @brief Execute a DOOF_CMD_READ_DSP command
508 *
509 * @attention This needs better documentation.
510 *
511 * @param f the device context
512 * @param address the DSP address to read
513 * @param len the payload length?
514 * @param intbuf memory location to store response
515 * @return an fblib_err representing success or failure
516 */
517 fblib_err
readdsp(libfb_t * f,unsigned int address,size_t len,unsigned int * intbuf)518 readdsp (libfb_t * f, unsigned int address, size_t len, unsigned int *intbuf)
519 {
520 unsigned char buffer[1500];
521 DOOF_BLK *doof_blk;
522 ssize_t status;
523 fblib_err ret;
524
525 /* First token is cmd */
526 buffer[0] = 0;
527 buffer[1] = DOOF_CMD_READ_DSP;
528 doof_blk = (DOOF_BLK *) (buffer + 2);
529 doof_blk->addr = address;
530 doof_blk->len = len;
531
532 if (len == 0)
533 return FBLIB_EINVAL;
534
535
536 if (!udp_ready_write (f))
537 return FBLIB_EAGAIN;
538
539 write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2);
540
541 /* read back */
542 ret = poll_for_newpkt (f);
543 if (ret != FBLIB_ESUCCESS)
544 return ret;
545
546 status = read (f->udp_socket, buffer, sizeof (buffer));
547
548 if (buffer[1])
549 {
550 printf ("Error code reported from device: %d\n", buffer[1]);
551 return -buffer[1];
552 }
553
554 if (status != (len * 4 + sizeof (DOOF_BLK) + 2))
555 {
556 printf ("Error in byte-count received\n");
557 return -DOOF_RESP_BADSIZE;
558 }
559 memcpy ((void *) intbuf, (void *) buffer + sizeof (DOOF_BLK) + 2, len * 4);
560 return 0;
561 }
562
563 /** @brief Write to a DSP address
564 *
565 * @attention This needs better documentation.
566 *
567 * @param f the device context
568 * @param address the DSP address to write to
569 * @param len the payload length
570 * @param intbuf memory location of buffer
571 * @return an fblib_err representing success or failure
572 */
573 fblib_err
writedsp(libfb_t * f,unsigned int address,size_t len,unsigned int * intbuf)574 writedsp (libfb_t * f, unsigned int address, size_t len, unsigned int *intbuf)
575 {
576 unsigned char buffer[1500];
577 unsigned int *intptr;
578 ssize_t status;
579 fblib_err ret;
580
581 DOOF_BLK *doof_blk;
582 buffer[0] = 0;
583 buffer[1] = DOOF_CMD_WRITE_DSP;
584 doof_blk = (DOOF_BLK *) (buffer + 2);
585
586 doof_blk->addr = address;
587 doof_blk->len = len;
588
589 intptr = (unsigned int *) (buffer + sizeof (DOOF_BLK) + 2);
590 memcpy ((void *) intptr, intbuf, len * 4);
591 write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2 + len * 4);
592
593 /* read back */
594 ret = poll_for_newpkt (f);
595 if (ret != FBLIB_ESUCCESS)
596 return ret;
597
598 status = read (f->udp_socket, buffer, sizeof (buffer));
599
600 if (buffer[1])
601 {
602 fprintf (stderr, "Error code reported from device: %d\n", buffer[1]);
603 return -buffer[1];
604 }
605
606 if (status != (sizeof (DOOF_BLK) + 2))
607 return FBLIB_EBYTECOUNT;
608
609 return FBLIB_ESUCCESS;
610 }
611
612
613 /** @brief Set the echo canceller channel types for the entire DSP
614 *
615 * We only set one group of types at a time, mask represents which channels get those types.
616 *
617 * @param f the device context
618 * @param type the DSP channel type value
619 * @param mask array of masks, 32 bits (one bit per channel) for each span. Each array index is one span.
620 * @return an fblib_err representing success or failure
621 */
622 fblib_err
ec_set_chantype(libfb_t * f,unsigned char type,uint32_t * mask)623 ec_set_chantype (libfb_t * f, unsigned char type, uint32_t * mask)
624 {
625 unsigned char buffer[1500];
626 unsigned char *charptr;
627 ssize_t status;
628 unsigned int x;
629 fblib_err ret;
630 buffer[0] = type;
631 buffer[1] = DOOF_CMD_EC_CHAN_TYPE;
632 charptr = buffer + 2;
633
634 for (x = 0; x < 16; x++)
635 {
636 *charptr++ = (mask[x / 4] >> ((x % 4) * 8)) & 0xff;
637 }
638
639 if (!udp_ready_write (f))
640 return FBLIB_EAGAIN;
641
642 status = write (f->udp_socket, buffer, 4 * 4 + 2);
643 if (status == -1)
644 return FBLIB_EERRNO;
645
646 /* read back */
647 ret = poll_for_newpkt (f);
648 if (ret != FBLIB_ESUCCESS)
649 return ret;
650
651 status = read (f->udp_socket, buffer, sizeof (buffer));
652 if (buffer[1])
653 {
654 printf ("Error code reported from device: %d\n", buffer[1]);
655 return -buffer[1];
656 }
657
658 if (status != (2))
659 {
660 return FBLIB_EBYTECOUNT;
661 }
662 return FBLIB_ESUCCESS;
663 }
664
665 /** @brief Send a custom DOOF command over UDP
666 *
667 * @param f the device context
668 * @param cmd the DOOF command to send
669 * @param param optional parameters to the DOOF command
670 * @param buf payload to send with the command
671 * @param len the length of the payload
672 * @return an fblib_err representing success or failure
673 */
674 fblib_err
custom_cmd(libfb_t * f,unsigned char cmd,unsigned char param,char * buf,size_t len)675 custom_cmd (libfb_t * f, unsigned char cmd, unsigned char param, char *buf,
676 size_t len)
677 {
678 unsigned char buffer[1500];
679 ssize_t status;
680 fblib_err ret;
681
682 if (!udp_ready_write (f))
683 return FBLIB_EAGAIN;
684
685 buffer[0] = param;
686 buffer[1] = cmd;
687 memcpy ((void *) buffer + 2, buf, len);
688
689 status = write (f->udp_socket, buffer, 2 + len);
690 if (status == -1)
691 return FBLIB_EERRNO;
692
693 /* read back */
694 ret = poll_for_newpkt (f);
695 if (ret != FBLIB_ESUCCESS)
696 return ret;
697
698 status = read (f->udp_socket, buffer, sizeof (buffer));
699 if (status != (2))
700 {
701 printf ("Error in byte-count received\n");
702 return -DOOF_RESP_BADSIZE;
703 }
704
705 #ifdef DEBUG
706 fprintf (stderr, "{custom_cmd 0x%02X param 0x%02X resp 0x%02X}\n",
707 cmd, param, buffer[1]);
708 #endif
709
710 return -buffer[1];
711 }
712
713 /** @brief Send a custom DOOF command over UDP and block until a reply is received
714 *
715 * @param f the device context
716 * @param cmd the DOOF command to send
717 * @param param optional parameters to the DOOF command
718 * @param buf payload to send with the command
719 * @param len the length of the payload
720 * @param rbuf location to store the reply
721 * @param rlen the expected reply length
722 * @return an fblib_err representing success or failure
723 */
724 fblib_err
custom_cmd_reply(libfb_t * f,unsigned char cmd,unsigned char param,char * buf,size_t len,char * rbuf,size_t rlen)725 custom_cmd_reply (libfb_t * f, unsigned char cmd, unsigned char param,
726 char *buf, size_t len, char *rbuf, size_t rlen)
727 {
728 unsigned char buffer[1500];
729 ssize_t status;
730 fblib_err ret;
731
732 if (!udp_ready_write (f))
733 return FBLIB_EAGAIN;
734
735 buffer[0] = param;
736 buffer[1] = cmd;
737 memcpy ((void *) buffer + 2, buf, len);
738 status = write (f->udp_socket, buffer, 2 + len);
739
740 if (status == -1)
741 return FBLIB_EERRNO;
742
743 /* read back */
744 ret = poll_for_newpkt (f);
745 if (ret != FBLIB_ESUCCESS)
746 return ret;
747
748 status = read (f->udp_socket, buffer, sizeof (buffer));
749 if (status != (rlen + 2))
750 {
751 printf ("Error in byte-count received\n");
752 return -DOOF_RESP_BADSIZE;
753 }
754 memcpy ((void *) rbuf, buffer + 2, rlen);
755
756 #ifdef DEBUG
757 fprintf (stderr, "{custom_cmd_reply 0x%02X param 0x%02X resp 0x%02X}\n",
758 cmd, param, buffer[1]);
759 #endif
760
761 return -buffer[1];
762 }
763
764
765 /** @brief Needs documentation! */
766 fblib_err
readmem32(libfb_t * f,unsigned int address,size_t len,uint32_t * intbuf)767 readmem32 (libfb_t * f, unsigned int address, size_t len, uint32_t * intbuf)
768 {
769 unsigned char buffer[1500];
770 DOOF_BLK *doof_blk;
771 ssize_t status;
772 fblib_err ret;
773
774 /* First token is cmd */
775 buffer[0] = 2; /* Param 2 is for 32-byte */
776 buffer[1] = DOOF_CMD_READ_MEM;
777 doof_blk = (DOOF_BLK *) (buffer + 2);
778
779 doof_blk->addr = address;
780 doof_blk->len = len;
781
782 if (len == 0)
783 return FBLIB_EINVAL;
784
785 if (!udp_ready_write (f))
786 return FBLIB_EAGAIN;
787
788 status = write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2);
789 if (status == -1)
790 return FBLIB_EERRNO;
791
792 /* read back */
793 ret = poll_for_newpkt (f);
794 if (ret != FBLIB_ESUCCESS)
795 return ret;
796
797 status = read (f->udp_socket, buffer, sizeof (buffer));
798
799 if (buffer[1])
800 {
801 printf ("Error code reported from device: %d\n", buffer[1]);
802 return -buffer[1];
803 }
804
805 if (status != (len * 4 + sizeof (DOOF_BLK) + 2))
806 return FBLIB_EBYTECOUNT;
807
808 memcpy ((void *) intbuf, (void *) buffer + sizeof (DOOF_BLK) + 2, len * 4);
809 return FBLIB_ESUCCESS;
810 }
811
812
813 /** @brief Read arbitrary device memory address
814 *
815 * @param f the device context
816 * @param address the memory address to read
817 * @param len the length of the data to read
818 * @param charbuf location to store the result
819 * @return an fblib_err representing success or failure
820 */
821 fblib_err
readmem(libfb_t * f,unsigned int address,size_t len,char * charbuf)822 readmem (libfb_t * f, unsigned int address, size_t len, char *charbuf)
823 {
824 unsigned char buffer[1500];
825 DOOF_BLK *doof_blk;
826 ssize_t status;
827 fblib_err ret;
828
829 /* First token is cmd */
830 buffer[0] = 0;
831 buffer[1] = DOOF_CMD_READ_MEM;
832 doof_blk = (DOOF_BLK *) (buffer + 2);
833
834
835 doof_blk->addr = address;
836 doof_blk->len = len;
837
838 if (len == 0)
839 return FBLIB_EINVAL;
840
841 if (!udp_ready_write (f))
842 return FBLIB_EAGAIN;
843
844 status = write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2);
845 if (status == -1)
846 return FBLIB_EERRNO;
847
848 /* read back */
849 ret = poll_for_newpkt (f);
850 if (ret != FBLIB_ESUCCESS)
851 return ret;
852
853 status = read (f->udp_socket, buffer, sizeof (buffer));
854
855 if (buffer[1])
856 {
857 printf ("Error code reported from device: %d\n", buffer[1]);
858 return -buffer[1];
859 }
860
861 if (status != (len + sizeof (DOOF_BLK) + 2))
862 return FBLIB_EBYTECOUNT;
863
864 memcpy ((void *) charbuf, (void *) buffer + sizeof (DOOF_BLK) + 2, len);
865 return FBLIB_ESUCCESS;
866 }
867
868 /** @brief Update and then reset PMON counters/registers
869 *
870 *
871 * @param f the device context
872 * @param span the span on the transceiver to access, in the range 0 to 3
873 * @return an fblib_err representing success or failure
874 */
875 fblib_err
libfb_updat_pmon(libfb_t * f,uint8_t span)876 libfb_updat_pmon (libfb_t * f, uint8_t span)
877 {
878 fblib_err ret;
879
880 /* Force a transition from 0 to 1 */
881 ret = writeidt (f, span, 0xC2, 0x0);
882 if (ret != FBLIB_ESUCCESS)
883 return ret;
884
885 ret = writeidt (f, span, 0xC2, 0x2);
886 if (ret != FBLIB_ESUCCESS)
887 return ret;
888
889 return FBLIB_ESUCCESS;
890 }
891
892 /** @brief Read an IDT indirect PMON register
893 *
894 * Registers are 8-bit wide. Reading and companding two registers
895 * (like the LCV0/1 register as an example) is not supported. You must
896 * do this manually. UPDAT must also be sent manually via
897 * libfb_updat_pmon().
898 *
899 * @param f the device context
900 * @param span the span to read from
901 * @param address the register address to read
902 * @param data location to store 8-bit response
903 *
904 * @return an fblib_err representing success or failure
905 */
906 fblib_err
libfb_readidt_pmon(libfb_t * f,uint8_t span,uint8_t address,uint8_t * data)907 libfb_readidt_pmon (libfb_t * f, uint8_t span, uint8_t address,
908 uint8_t * data)
909 {
910 fblib_err ret;
911 uint8_t pmonaccess = (address & 0xF) | (((span % 2) & 0xF) << 5);
912 int devnum = 0;
913
914 switch (span)
915 {
916 case 0:
917 case 1:
918 devnum = 0;
919 break;
920 case 2:
921 case 3:
922 devnum = 2;
923 break;
924 }
925
926 /* Set ADDR and LINKSEL0 */
927 ret = writeidt (f, devnum, 0x00E, pmonaccess);
928 if (ret != FBLIB_ESUCCESS)
929 return ret;
930
931 /* Read DAT */
932 ret = readidt (f, devnum, 0x00F, 1, (char *) data);
933 if (ret != FBLIB_ESUCCESS)
934 return ret;
935
936 return FBLIB_ESUCCESS;
937 }
938
939 /** @brief Write arbitrary transceiver register
940 *
941 * The address should be of the form 0xAB. The span parameter is used
942 * to expand the address into the IDT native register address form of
943 * 0xXAB where X is the correct span number on the targeted device.
944 *
945 * @param f the device context
946 * @param span the span we wish to write to
947 * @param address the register to write to
948 * @param data the 8-bit data to write
949 * @return an fblib_err representing success or failure
950 */
951 fblib_err
writeidt(libfb_t * f,unsigned char span,uint8_t address,uint8_t data)952 writeidt (libfb_t * f, unsigned char span, uint8_t address, uint8_t data)
953 {
954 uint8_t buffer[2];
955
956 buffer[0] = address;
957 buffer[1] = data;
958
959 return custom_cmd (f, DOOF_CMD_IDT_WRITE_REG, span, buffer, 2);
960 }
961
962 /** @brief Read arbitrary transceiver memory address
963 *
964 * The address should be of the form 0xAB. The span parameter is used
965 * to expand the address into the IDT native register address form of
966 * 0xXAB where X is the correct span number on the targeted device.
967 *
968 * @param f the device context
969 * @param span the transceiver we wish to read from
970 * @param address the memory address to read
971 * @param len the length of the data to read
972 * @param charbuf location to store the result
973 * @return an fblib_err representing success or failure
974 */
975 fblib_err
readidt(libfb_t * f,unsigned char span,unsigned int address,size_t len,char * charbuf)976 readidt (libfb_t * f, unsigned char span, unsigned int address, size_t len,
977 char *charbuf)
978 {
979 unsigned char buffer[1500];
980 DOOF_BLK *doof_blk;
981 ssize_t status;
982 fblib_err ret;
983
984 /* First token is cmd */
985 buffer[0] = span;
986 buffer[1] = DOOF_CMD_READ_IDT_REG;
987 doof_blk = (DOOF_BLK *) (buffer + 2);
988
989 doof_blk->addr = address;
990 doof_blk->len = len;
991
992 if (len == 0)
993 return FBLIB_EINVAL;
994
995 if (!udp_ready_write (f))
996 return FBLIB_EAGAIN;
997
998 status = write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2);
999 if (status == -1)
1000 return FBLIB_EERRNO;
1001
1002 /* read back */
1003 ret = poll_for_newpkt (f);
1004 if (ret != FBLIB_ESUCCESS)
1005 return ret;
1006
1007 status = read (f->udp_socket, buffer, sizeof (buffer));
1008
1009 if (status >= 2 && buffer[1])
1010 {
1011 printf ("Error code reported from device: %d\n", buffer[1]);
1012 return -buffer[1];
1013 }
1014
1015 if (status != (len + sizeof (DOOF_BLK) + 2))
1016 return FBLIB_EBYTECOUNT;
1017
1018 memcpy ((void *) charbuf, (void *) buffer + sizeof (DOOF_BLK) + 2, len);
1019 return FBLIB_ESUCCESS;
1020 }
1021
1022 /** @brief Get the GPAK_FLASH_PARMS information from a device
1023 *
1024 * @param f the device context
1025 * @param buf location to store the GPAK_FLASH_PARMS
1026 * @return an fblib_err representing success or failure
1027 */
1028 fblib_err
fblib_get_gpakparms(libfb_t * f,GPAK_FLASH_PARMS * buf)1029 fblib_get_gpakparms (libfb_t * f, GPAK_FLASH_PARMS * buf)
1030 {
1031 unsigned char buffer[1500];
1032 ssize_t status;
1033 fblib_err ret;
1034
1035 if (buf == NULL)
1036 return FBLIB_EINVAL;
1037
1038 /* First token is cmd */
1039 buffer[0] = 0;
1040 buffer[1] = DOOF_CMD_GET_GPAK_FLASH_PARMS;
1041
1042 if (!udp_ready_write (f))
1043 return FBLIB_EAGAIN;
1044
1045 write (f->udp_socket, buffer, 2);
1046
1047 /* read back */
1048 ret = poll_for_newpkt (f);
1049 if (ret != FBLIB_ESUCCESS)
1050 return ret;
1051
1052 status = read (f->udp_socket, buffer, sizeof (buffer));
1053
1054 if (buffer[1])
1055 {
1056 printf ("Error code reported from device: %d\n", buffer[1]);
1057 return -buffer[1];
1058 }
1059
1060 if (status != (sizeof (GPAK_FLASH_PARMS) + 2))
1061 return FBLIB_EBYTECOUNT;
1062
1063 memcpy (buf, buffer + 2, sizeof (GPAK_FLASH_PARMS));
1064 return FBLIB_ESUCCESS;
1065 }
1066
1067 /** @brief Read a SPI register
1068 *
1069 * @param f the device context
1070 * @param dev the SPI device address
1071 * @param address the memory address to read from the device, `dev'
1072 * @param len the length of data to read
1073 * @param charbuf location to store the result
1074 * @return an fblib_err representing success or failure
1075 */
1076 fblib_err
readspi(libfb_t * f,unsigned char dev,unsigned char address,size_t len,char * charbuf)1077 readspi (libfb_t * f, unsigned char dev, unsigned char address, size_t len,
1078 char *charbuf)
1079 {
1080 unsigned char buffer[1500];
1081 DOOF_BLK *doof_blk;
1082 ssize_t status;
1083 fblib_err ret;
1084
1085 /* First token is cmd */
1086 buffer[0] = dev;
1087 buffer[1] = DOOF_CMD_SPI_READREG;
1088 doof_blk = (DOOF_BLK *) (buffer + 2);
1089
1090 doof_blk->addr = address;
1091 doof_blk->len = len;
1092
1093 if (len == 0)
1094 return FBLIB_EINVAL;
1095
1096 if (!udp_ready_write (f))
1097 return FBLIB_EAGAIN;
1098
1099 status = write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2);
1100 if (status == -1)
1101 return FBLIB_EERRNO;
1102
1103 /* read back */
1104 ret = poll_for_newpkt (f);
1105 if (ret != FBLIB_ESUCCESS)
1106 return ret;
1107
1108 status = read (f->udp_socket, buffer, sizeof (buffer));
1109
1110 if (buffer[1])
1111 {
1112 printf ("Error code reported from device: %d\n", buffer[1]);
1113 return -buffer[1];
1114 }
1115
1116 if (status != (len + sizeof (DOOF_BLK) + 2))
1117 return FBLIB_EBYTECOUNT;
1118
1119 memcpy ((void *) charbuf, (void *) buffer + sizeof (DOOF_BLK) + 2, len);
1120 return FBLIB_ESUCCESS;
1121 }
1122
1123 /** @brief Write to a SPI register
1124 *
1125 * @param f the device context
1126 * @param dev the SPI device address
1127 * @param address the memory address to write to the device, `dev'
1128 * @param len the length of data to write
1129 * @param charbuf location to data payload
1130 * @return an fblib_err representing success or failure
1131 */
1132 fblib_err
writespi(libfb_t * f,unsigned char dev,unsigned char address,size_t len,char * charbuf)1133 writespi (libfb_t * f, unsigned char dev, unsigned char address, size_t len,
1134 char *charbuf)
1135 {
1136 DOOF_BLK *doof_blk;
1137 unsigned char buffer[1500];
1138 unsigned char *charptr;
1139 ssize_t status;
1140 fblib_err ret;
1141
1142
1143 buffer[0] = dev;
1144 buffer[1] = DOOF_CMD_SPI_WRITEREG;
1145 doof_blk = (DOOF_BLK *) (buffer + 2);
1146
1147 doof_blk->addr = address;
1148 doof_blk->len = len;
1149
1150 charptr = (unsigned char *) (buffer + sizeof (DOOF_BLK) + 2);
1151 memcpy ((void *) charptr, charbuf, len);
1152
1153 if (!udp_ready_write (f))
1154 return FBLIB_EAGAIN;
1155
1156 status = write (f->udp_socket, buffer, sizeof (DOOF_BLK) + 2 + len);
1157 if (status == -1)
1158 return FBLIB_EERRNO;
1159
1160 /* read back */
1161 ret = poll_for_newpkt (f);
1162 if (ret != FBLIB_ESUCCESS)
1163 return ret;
1164
1165 status = read (f->udp_socket, buffer, sizeof (buffer));
1166
1167 if (status == -1)
1168 return FBLIB_EERRNO;
1169
1170 if (buffer[1])
1171 {
1172 printf ("Error code reported from device: %d\n", buffer[1]);
1173 return -buffer[1];
1174 }
1175
1176 if (status != (sizeof (DOOF_BLK) + 2))
1177 return FBLIB_EBYTECOUNT;
1178
1179 return FBLIB_ESUCCESS;
1180 }
1181
1182 /** @brief get the current link configuration over UDP
1183 *
1184 * @param f the device context
1185 * @param link_cfg A memory location that is at least IDT_LINKS*sizeof(IDT_LINK_CONFIG) long
1186 * @return an fblib_err representing success or failure
1187 */
1188 fblib_err
configcheck_fb_udp(libfb_t * f,IDT_LINK_CONFIG * link_cfg)1189 configcheck_fb_udp (libfb_t * f, IDT_LINK_CONFIG * link_cfg)
1190 {
1191 int len = 2 + IDT_LINKS * sizeof (IDT_LINK_CONFIG);
1192 unsigned char buffer[len];
1193 ssize_t status;
1194 fblib_err ret;
1195
1196 memset ((void *) buffer, 0, len);
1197 buffer[0] = 0x0; /* Don't configure any spans */
1198 buffer[1] = DOOF_CMD_RECONFIG;
1199 status = write (f->udp_socket, buffer, len);
1200
1201 if (status == -1)
1202 return FBLIB_EERRNO;
1203
1204 /* read back */
1205 ret = poll_for_newpkt (f);
1206 if (ret != FBLIB_ESUCCESS)
1207 return ret;
1208
1209 status = read (f->udp_socket, buffer, sizeof (buffer));
1210
1211 if (status == -1)
1212 return FBLIB_EERRNO;
1213
1214 if (buffer[1])
1215 {
1216 printf ("Error code reported from device: %d\n", buffer[1]);
1217 return -buffer[1];
1218 }
1219
1220 if (status != len)
1221 return FBLIB_EBYTECOUNT;
1222
1223 memcpy ((void *) link_cfg, &buffer[2],
1224 sizeof (IDT_LINK_CONFIG) * IDT_LINKS);
1225 return FBLIB_ESUCCESS;
1226 }
1227
1228 /** @brief configure a device using span_mode masks with no LBO information
1229 * @deprecated span_mode masks are no longer used for configuration
1230 *
1231 * @param f the device context
1232 * @param span_mode configuration masks
1233 * @return an fblib_err representing success or failure
1234 */
1235 fblib_err
config_fb_udp(libfb_t * f,unsigned char * span_mode)1236 config_fb_udp (libfb_t * f, unsigned char *span_mode)
1237 {
1238 unsigned char zero[] = { 0, 0, 0, 0 };
1239 return config_fb_udp_lbo (f, span_mode, zero);
1240 }
1241
1242 /** @brief configure a device using modern IDT_LINK_CONFIG data structures
1243 *
1244 * @param f the device context
1245 * @param configs an array of IDT_LINK_CONFIG structures, one for each span
1246 * @return an fblib_err representing success or failure
1247 */
1248 fblib_err
config_fb_udp_linkconfig(libfb_t * f,IDT_LINK_CONFIG * configs)1249 config_fb_udp_linkconfig (libfb_t * f, IDT_LINK_CONFIG * configs)
1250 {
1251 int len, span;
1252 unsigned char buffer[1500];
1253 ssize_t status;
1254 fblib_err ret;
1255 IDT_LINK_CONFIG *link_cfg;
1256
1257 memset ((void *) buffer, 0, sizeof (buffer));
1258
1259 /* Reconfigure all spans */
1260 buffer[0] = 0xF;
1261 buffer[1] = DOOF_CMD_RECONFIG;
1262 link_cfg = (IDT_LINK_CONFIG *) & (buffer[2]);
1263 for (span = 0; span < IDT_LINKS; span++)
1264 memcpy (&link_cfg[span], &configs[span], sizeof (IDT_LINK_CONFIG));
1265
1266 len = 2 + IDT_LINKS * sizeof (IDT_LINK_CONFIG);
1267 if (!udp_ready_write (f))
1268 return FBLIB_EAGAIN;
1269
1270 status = write (f->udp_socket, buffer, len);
1271 if (status == -1)
1272 return FBLIB_EERRNO;
1273
1274 /* read back */
1275 ret = poll_for_newpkt (f);
1276 if (ret != FBLIB_ESUCCESS)
1277 return ret;
1278
1279 status = read (f->udp_socket, buffer, sizeof (buffer));
1280
1281 if (status == -1)
1282 return FBLIB_EERRNO;
1283
1284 if (buffer[1])
1285 {
1286 printf ("Error code reported from device: %d\n", buffer[1]);
1287 return -buffer[1];
1288 }
1289
1290 if (status != len)
1291 {
1292 printf ("Error in byte-count received\n");
1293 return -DOOF_RESP_BADSIZE;
1294 }
1295 return 0;
1296 }
1297
1298 /** @brief configure a device using span_mode masks with LBO information
1299 * @deprecated span_mode masks are no longer used for configuration
1300 *
1301 * @param f the device context
1302 * @param span_mode configuration masks
1303 * @param puls an array of LBO, PULS_* settings, one for each span
1304 * @return an fblib_err representing success or failure
1305 */
1306 fblib_err
config_fb_udp_lbo(libfb_t * f,unsigned char * span_mode,unsigned char * puls)1307 config_fb_udp_lbo (libfb_t * f, unsigned char *span_mode, unsigned char *puls)
1308 {
1309 int len, span;
1310 unsigned char buffer[1500];
1311 IDT_LINK_CONFIG *link_cfg;
1312 ssize_t status;
1313 fblib_err ret;
1314
1315 memset ((void *) buffer, 0, sizeof (buffer));
1316
1317 /* Reconfig all spans */
1318 buffer[0] = 0xF;
1319 buffer[1] = DOOF_CMD_RECONFIG;
1320 link_cfg = (IDT_LINK_CONFIG *) & (buffer[2]);
1321
1322 for (span = 0; span < IDT_LINKS; span++)
1323 {
1324 if (span_mode[span] & SPAN_MODE_E1)
1325 link_cfg->E1Mode = 1;
1326 if (span_mode[span] & SPAN_MODE_ESF)
1327 link_cfg->framing = 1;
1328 if (span_mode[span] & SPAN_MODE_AMI)
1329 link_cfg->encoding = 1;
1330 if (span_mode[span] & SPAN_MODE_RBS)
1331 link_cfg->rbs_en = 1;
1332 if (span_mode[span] & SPAN_MODE_CRCMF)
1333 link_cfg->CRCMF = 1;
1334 if (span_mode[span] & SPAN_MODE_RLB)
1335 link_cfg->rlb = 1;
1336 if (span_mode[span] & SPAN_MODE_EQ)
1337 link_cfg->EQ = 1;
1338 if (span_mode[span] & SPAN_MODE_HDLC)
1339 link_cfg->HDLC = 0x3;
1340
1341 if (link_cfg->E1Mode == 0)
1342 {
1343 /* PULS[3:0] only for T1/J1 */
1344 link_cfg->LBO = puls[span] & 0xF;
1345 }
1346 else
1347 {
1348 /* Just ensure PULS[3:0] is 0 for E1 */
1349 link_cfg->LBO = 0;
1350 }
1351
1352 link_cfg++;
1353 }
1354 len = 2 + IDT_LINKS * sizeof (IDT_LINK_CONFIG);
1355
1356 #ifdef DEBUG
1357 fprintf (stderr, "LBO PULS: ");
1358 for (span = 0; span < IDT_LINKS; span++)
1359 {
1360 fprintf (stderr, "%02X ", puls[span] & 0xF);
1361 }
1362 fprintf (stderr, "\n");
1363 fprintf (stderr, "Uniform(?) span mode: 0x%02X\n", span_mode[0]);
1364 #endif
1365
1366 if (!udp_ready_write (f))
1367 return FBLIB_EAGAIN;
1368
1369 status = write (f->udp_socket, buffer, len);
1370 if (status == -1)
1371 return FBLIB_EERRNO;
1372
1373 /* read back */
1374 ret = poll_for_newpkt (f);
1375 if (ret != FBLIB_ESUCCESS)
1376 return ret;
1377 #ifdef DEBUG
1378 fprintf (stderr, "Configured UDP socket %d\n", f->udp_socket);
1379 #endif
1380 status = read (f->udp_socket, buffer, sizeof (buffer));
1381
1382 if (status == -1)
1383 return FBLIB_EERRNO;
1384
1385 if (buffer[1])
1386 {
1387 printf ("Error code reported from device: %d\n", buffer[1]);
1388 return -buffer[1];
1389 }
1390
1391 if (status != len)
1392 {
1393 printf ("Error in byte-count received\n");
1394 return -DOOF_RESP_BADSIZE;
1395 }
1396 return 0;
1397 }
1398
1399
1400 /** @brief check if CRC checking is enabled
1401 * @param f the device context
1402 * @return true if CRC checking is enabled
1403 */
1404 bool
libfb_getcrc(libfb_t * f)1405 libfb_getcrc (libfb_t * f)
1406 {
1407 if (f->crc_en == 1)
1408 return true;
1409 return false;
1410 }
1411
1412 /** @brief set CRC checking value
1413 * @param f the device context
1414 * @param value 1 for enabling check, 0 to disable
1415 */
1416 static inline void
libfb_set_crc(libfb_t * f,int value)1417 libfb_set_crc (libfb_t * f, int value)
1418 {
1419 f->crc_en = value;
1420 }
1421
1422 /** @brief toggle CRC checking on
1423 * @param f the device context
1424 */
1425 void
libfb_setcrc_on(libfb_t * f)1426 libfb_setcrc_on (libfb_t * f)
1427 {
1428 return libfb_set_crc (f, 1);
1429 }
1430
1431 /** @brief toggle CRC checking off
1432 * @param f the device context
1433 */
1434 void
libfb_setcrc_off(libfb_t * f)1435 libfb_setcrc_off (libfb_t * f)
1436 {
1437 return libfb_set_crc (f, 0);
1438 }
1439
1440 /** @brief Get the (local) source MAC address
1441 * @return pointer to the 6-byte MAC address
1442 */
1443 u_int8_t *
libfb_getsrcmac(libfb_t * f)1444 libfb_getsrcmac (libfb_t * f)
1445 {
1446 return f->s_mac;
1447 }
1448