]> rtime.felk.cvut.cz Git - frescor/fna.git/blob - src_frescan/frescan.c
f34af654ea59a0c48d230ddef55c13320cc3c206
[frescor/fna.git] / src_frescan / frescan.c
1 /*!
2  * @file frescan.c
3  *
4  * @brief the FRESCAN protocol
5  *
6  * @version 0.01
7  *
8  * @date 20-Feb-2008
9  *
10  * @author
11  *      Daniel Sangorrin
12  *
13  * @comments
14  *
15  * This file contains the implementation of the FRESCAN protocol
16  *
17  * @license
18  *
19  * See MaRTE OS license
20  *
21  */
22
23 #include <sys/marte_configuration_parameters.h> // PATH_MX
24 #include <fcntl.h>  // open
25 #include <unistd.h> // ioctl
26 #include <stdlib.h> // malloc
27 #include <string.h> // memcpy
28
29 #include <drivers/can.h>       // can_chip_t, can_frame_t
30 #include "frescan.h"           // frescan_init_params_t, frescan_send_params_t
31 #include "frescan_queues.h"    // init, enqueue, requeue
32 #include "frescan_data.h"      // init, the_networks
33 #include "frescan_servers.h"   // init, frame_sent
34 #include "frescan_debug.h"     // DEBUG
35 #include "frescan_id.h"        // frescan_id_set_field, frescan_id_get_field
36 #include "frescan_hw_buffer.h" // frescan_hw_buffer_update
37 #include "frescan_packets.h"
38
39 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
40                                     struct can_frame_t *frame);
41
42 static int frescan_hook_frame_sent(const struct can_chip_t *chip);
43
44 static int frescan_hook_frame_aborted(const struct can_chip_t *chip);
45
46 /**
47  * frescan_init - initializes the network and the internal structures
48  *
49  * @params: the initialization parameters
50  *
51  * This function initializes the frescan network protocol.
52  *
53  * First it opens and configures the corresponding CAN chip device. For the
54  * CAN chip acceptance filter we use a dual filter configuration. The first
55  * filter is to set my local address address and the second one is to allow
56  * broadcast messages.
57  *
58  * Once the CAN chip is configured we call the initialization functions of
59  * the rest of modules of frescan.
60  *
61  */
62
63 int frescan_init(frescan_init_params_t *params)
64 {
65         int fd, ret;
66         char can_path[PATH_MX];
67         struct ioctl_filters_t ioctl_filters;
68         struct can_filter_t filters[2];
69
70         snprintf(can_path, PATH_MX, "/dev/can%u", params->net);
71
72         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "open %s\n", can_path);
73
74         fd = open (can_path, O_RDWR);
75         if (fd == -1) {
76                 ERROR ("could not open /dev/can%u\n", params->net);
77                 return -1;
78         }
79
80         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set acceptance filters\n");
81
82         filters[0].mask = 0xFFFFFFFF;
83         frescan_id_set_field(&filters[0].mask, FRESCAN_FIELD_DEST,0x00);
84         filters[0].code = 0;
85         frescan_id_set_field(&filters[0].code, FRESCAN_FIELD_DEST,params->node);
86
87         filters[1].mask = filters[0].mask;
88         filters[1].code = 0;
89         frescan_id_set_field(&filters[1].code,
90                              FRESCAN_FIELD_DEST,
91                              FRESCAN_BROADCAST_ADDR);
92
93         ioctl_filters.filters = filters;
94         ioctl_filters.len = 2;
95
96         ret = ioctl(fd, CAN_IOCTL_SET_FILTERS, &ioctl_filters);
97         if (ret == -1) {
98                 ERROR ("ioctl CAN_IOCTL_SET_FILTERS failed /dev/can%u\n",
99                        params->net);
100                 return -1;
101         }
102
103         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "set tx, rx, abort hooks\n");
104
105         ret = ioctl(fd, CAN_IOCTL_SET_TX_HOOK, frescan_hook_frame_sent);
106         if (ret == -1) {
107                 ERROR ("ioctl CAN_IOCTL_SET_TX_HOOK failed /dev/can%u\n",
108                        params->net);
109                 return -1;
110         }
111
112         ret = ioctl(fd, CAN_IOCTL_SET_RX_HOOK, frescan_hook_frame_recv);
113         if (ret == -1) {
114                 ERROR ("ioctl CAN_IOCTL_SET_RX_HOOK failed /dev/can%u\n",
115                        params->net);
116                 return -1;
117         }
118
119         ret = ioctl(fd, CAN_IOCTL_SET_AB_HOOK, frescan_hook_frame_aborted);
120         if (ret == -1) {
121                 ERROR ("ioctl CAN_IOCTL_SET_AB_HOOK failed /dev/can%u\n",
122                        params->net);
123                 return -1;
124         }
125
126         DEBUG(FRESCAN_INIT_ENABLE_DEBUG, "init the rest of modules\n");
127
128         ret = frescan_data_init(fd, params);
129         if (ret != 0) {
130                 ERROR("could not initialize the global data\n");
131                 return -1;
132         }
133
134         ret = frescan_packets_init();
135         if (ret != 0) {
136                 ERROR("could not initialize the packets pool\n");
137                 return -1;
138         }
139
140         ret = frescan_queues_init(&the_networks[params->net].queues, params);
141         if (ret != 0) {
142                 ERROR("could not initialize the queues\n");
143                 return -1;
144         }
145
146         ret = frescan_servers_init(params->net);
147         if (ret != 0) {
148                 ERROR("could not initialize the servers\n");
149                 return -1;
150         }
151
152         return 0;
153 }
154
155 /**
156  * frescan_send - send a message
157  *
158  * @params: the parameters needed by the protocol to send the message
159  * @msg: the message buffer
160  * @size: the size of the message
161  *
162  * This is one of the main functions of the protocol and it provides the
163  * means to send a message through the protocol stack.
164  */
165
166 int frescan_send(const frescan_send_params_t *params,
167                  const uint8_t *msg,
168                  const size_t size)
169 {
170         int ret;
171         frescan_packet_t *packet;
172         frescan_prio_queue_t *pqueue;
173
174         DEBUG(FRESCAN_SEND_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
175               "checking arguments (msg size=%d)\n", size);
176
177         if ((params == NULL) || (msg == NULL) || (size == 0)) {
178                 ERROR("arguments are not ok\n");
179                 return -1;
180         }
181
182         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a packet\n");
183
184         FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
185         packet = frescan_packets_alloc();
186         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
187
188         if (packet == NULL) {
189                 ERROR("could not allocate packet\n");
190                 return -1;
191         }
192         packet->flags = params->flags; // set the flags (to remember them)
193
194         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "allocating a frame\n");
195
196         FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
197         packet->frame = can_framespool_alloc();
198         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
199
200         if (packet->frame == NULL) {
201                 ERROR("could not allocate frame\n");
202                 return -1;
203         }
204
205         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "set values for the frame header\n");
206         packet->frame->is_extended_format = true;
207         packet->frame->is_rtr = false;
208
209         if (params->flags & FRESCAN_FP) {
210                 // NOTE: frag id for fp is: FRESCAN_MX_IDS, so the servers can
211                 // have IDs in the range (0 .. FRESCAN_MX_IDS-1)
212                 frescan_id_set_field(&packet->frame->id,
213                                      FRESCAN_FIELD_FRAG_ID,
214                                      (uint32_t)FRESCAN_MX_IDS);
215
216                 frescan_id_set_field(&packet->frame->id,
217                                       FRESCAN_FIELD_PRIO,
218                                       (uint32_t)params->prio);
219         } else {
220                 // NOTE: the priority is put when the packet is dequeued
221                 // and it is the priority of th server
222                 frescan_id_set_field(&packet->frame->id,
223                                      FRESCAN_FIELD_FRAG_ID,
224                                      (uint32_t)params->ss);
225         }
226
227         frescan_id_set_field(&packet->frame->id,
228                              FRESCAN_FIELD_DEST,
229                              (uint32_t)params->to);
230
231         frescan_id_set_field(&packet->frame->id,
232                              FRESCAN_FIELD_SRC,
233                              (uint32_t)the_networks[params->net].local_node);
234
235         frescan_id_set_field(&packet->frame->id,
236                               FRESCAN_FIELD_CHAN,
237                               (uint32_t)params->channel);
238
239         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "set the packet data bytes\n");
240         if (params->flags & FRESCAN_ASYNC) {
241                 // allocate a buffer and copy the data
242                 // NOTE: instead of this we could use a chain of frames but
243                 // i think it would be inefficient since each one can only
244                 // hold 8 user bytes and we need to write its headers.
245                 packet->buffer_head = (uint8_t *)malloc(size*sizeof(uint8_t));
246                 memcpy(packet->buffer_head, msg, size);
247         } else {
248                 packet->buffer_head = (uint8_t *)msg;
249         }
250
251         packet->buffer_read_pointer = packet->buffer_head;
252         packet->buffer_pending_bytes = size;
253         pqueue = the_networks[params->net].queues.tx_fp_queue;
254
255         DEBUG(FRESCAN_SEND_ENABLE_DEBUG, "enqueue the packet\n");
256         if (packet->flags & FRESCAN_FP) {
257                 FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
258                 ret = frescan_pqueue_enqueue(pqueue, packet, params->prio);
259                 FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
260
261                 if (ret != 0) {
262                         ERROR("could not enqueue the packet\n");
263                         return -1;
264                 }
265         } else {
266                 FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
267                 ret = frescan_servers_enqueue(params->net, params->ss, packet);
268                 FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
269
270                 if (ret != 0) {
271                         ERROR("could not enqueue the packet\n");
272                         return -1;
273                 }
274         }
275
276         FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
277         ret = frescan_hw_buffer_update(params->net);
278         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
279
280         if (ret != 0) {
281                 ERROR("could not update hw buffer\n");
282                 return -1;
283         }
284
285         return 0;
286 }
287
288 /**
289  * frescan_recv - receive a message
290  *
291  * @params: the parameters needed by the protocol to receive the message
292  * @msg: the message buffer
293  * @size: the size of the message buffer
294  * @recv_bytes: the number of bytes received
295  * @from: the node that sent the message
296  * @prio: the priority of the message
297  *
298  * This is one of the main functions of the protocol and it provides the
299  * means to receive a message through the protocol stack.
300  */
301
302 int frescan_recv(const frescan_recv_params_t *params,
303                  uint8_t *msg,
304                  const size_t size,
305                  size_t *recv_bytes,
306                  frescan_node_t *from,
307                  frescan_prio_t *prio)
308 {
309         int ret;
310         frescan_prio_queue_t *pqueue;
311         bool blocking;
312         frescan_packet_t *head, *packet;
313
314         if (params->flags & FRESCAN_SYNC) {
315                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
316                       "receive a packet in blocking mode\n");
317                 blocking = true;
318         } else {
319                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
320                       "receive a packet in non-blocking mode\n");
321                 blocking = false;
322         }
323
324         pqueue = the_networks[params->net].queues.rx_channel_queues
325                                                              [params->channel];
326
327         ret = frescan_pqueue_dequeue(pqueue, &head, prio, blocking);
328         if (ret != 0) {
329                 ERROR ("could not dequeue packet\n");
330                 return -1;
331         }
332
333         if (head == NULL) {
334                 if (blocking == false) {
335                         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
336                               "blocking false, no packets\n");
337                         *recv_bytes = 0;
338                         return 0;
339                 } else {
340                         ERROR ("blocking true, and packet = null\n");
341                         return -1;
342                 }
343         }
344
345         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
346               "traverse the list of packets for this message\n");
347
348         *recv_bytes = 0;
349
350         FRESCAN_ACQUIRE_LOCK(&the_networks[params->net].lock);
351
352         list_for_each_entry(packet, &head->msg_list, msg_list) {
353                 // TODO: memory checks, delete the packets
354                 memcpy(msg + *recv_bytes,
355                        packet->frame->data,
356                        packet->frame->dlc);
357                 *recv_bytes += packet->frame->dlc;
358
359                 *from = (frescan_node_t)frescan_id_get_field(packet->frame->id,
360                                                              FRESCAN_FIELD_SRC);
361                 DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
362                       "ID Packet, dlc: %u, frame pool pos: %u, from:%u\n",
363                       packet->frame->dlc, packet->frame->pool_pos, *from);
364
365                 ret = can_framespool_free(packet->frame);
366                 if (ret != 0) {
367                         ERROR("could not free frame\n");
368                         return -1;
369                 }
370
371                 ret = frescan_packets_free(packet);
372                 if (ret != 0) {
373                         ERROR("could not free packet\n");
374                         return -1;
375                 }
376         }
377
378         ret = frescan_packets_free(head);
379
380         FRESCAN_RELEASE_LOCK(&the_networks[params->net].lock);
381
382         if (ret != 0) {
383                 ERROR("could not free head packet\n");
384                 return -1;
385         }
386
387         DEBUG(FRESCAN_RECV_ENABLE_DEBUG,
388               "received bytes: %u\n", *recv_bytes);
389
390         return 0;
391 }
392
393
394 /**
395  * frescan_hook_frame_recv - frame received hook
396  *
397  * This function will be called by the CAN driver's IRQ handler when a frame
398  * is received so we can store it in an appropiate queue.
399  *
400  * NOTE: in the future it could consist simply of signaling a semaphore to
401  * let a bottom half thread do the hard work.
402  */
403
404
405 static int frescan_hook_frame_recv (const struct can_chip_t *chip,
406                                     struct can_frame_t *frame)
407 {
408         int i, ret;
409         uint32_t prio, dest, src, channel, frag_id, frag_flag;
410         frescan_packet_t *packet, *head;
411         frescan_prio_queue_t *pqueue;
412         int net;
413
414         net = chip->minor;
415
416         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG, "received a frame, net=%d\n", net);
417         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
418               "%s %s, id=0x%X, dlc=%u, pool:%u\n",
419               (frame->is_extended_format) ? "Ext" : "Stnd",
420               (frame->is_rtr) ? "RTR Frame" : "DATA Frame",
421               frame->id,
422               frame->dlc,
423               frame->pool_pos);
424
425         for (i=0; i<frame->dlc; i++) {
426                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG,
427                       "data[%d] = 0x%X;\n", i, frame->data[i]);
428         }
429
430         prio      = frescan_id_get_field(frame->id, FRESCAN_FIELD_PRIO);
431         dest      = frescan_id_get_field(frame->id, FRESCAN_FIELD_DEST);
432         src       = frescan_id_get_field(frame->id, FRESCAN_FIELD_SRC);
433         channel   = frescan_id_get_field(frame->id, FRESCAN_FIELD_CHAN);
434         frag_id   = frescan_id_get_field(frame->id, FRESCAN_FIELD_FRAG_ID);
435         frag_flag = frescan_id_get_field(frame->id, FRESCAN_FIELD_FRAG_FLAG);
436
437         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
438               "prio:%u dest:%u src:%u chan:%u id:%u flag:%u\n",
439               prio, dest, src, channel, frag_id, frag_flag);
440
441         DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG,
442               "enqueue the packet in ID queue\n");
443         packet = frescan_packets_alloc();
444         packet->frame = frame;
445
446         if (frag_id == FRESCAN_MX_IDS) {
447                 head = the_networks[net].id_fp_queues[src][prio];
448         } else {
449                 head = the_networks[net].id_queues[src][frag_id];
450         }
451
452         if (head == NULL) {
453                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
454                                 FRESCAN_FRAG_ENABLE_DEBUG,
455                 "allocate head for id=%u\n", frag_id);
456                 head = frescan_packets_alloc();
457                 INIT_LIST_HEAD(&head->msg_list);
458
459                 if (frag_id == FRESCAN_MX_IDS) {
460                         the_networks[net].id_fp_queues[src][prio] = head;
461                 } else {
462                         the_networks[net].id_queues[src][frag_id] = head;
463                 }
464         }
465
466         list_add_tail(&packet->msg_list, &head->msg_list);
467
468         if (frag_flag == false) {
469                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
470                                 FRESCAN_FRAG_ENABLE_DEBUG,
471                 "message complete, move msg to channel\n");
472                 // TODO: select the highest priority??
473                 pqueue = the_networks[net].queues.rx_channel_queues[channel];
474                 ret = frescan_pqueue_enqueue(pqueue, head, prio);
475                 if (ret != 0) {
476                         ERROR("could not enqueue message in channel queue\n");
477                         return -1;
478                 }
479
480                 if (frag_id == FRESCAN_MX_IDS) {
481                         the_networks[net].id_fp_queues[src][prio] = NULL;
482                 } else {
483                         the_networks[net].id_queues[src][frag_id] = NULL;
484                 }
485
486         } else {
487                 DEBUG(FRESCAN_RX_HOOK_ENABLE_DEBUG ||
488                                 FRESCAN_FRAG_ENABLE_DEBUG,
489                 "message not complete, wait for more fragments\n");
490         }
491
492         // NOTE: don't forget to free the frame and the packet when it is
493         // read by the user application
494
495         return 0;
496 };
497
498 /**
499  * frescan_hook_frame_sent - frame sent hook
500  *
501  * This function will be called by the CAN driver's IRQ handler when a frame
502  * is sent through the CAN bus so we can enqueue another one, signal a
503  * semaphore, consume sporadic server capacity...
504  */
505
506 static int frescan_hook_frame_sent(const struct can_chip_t *chip)
507 {
508         int ret;
509         frescan_packet_t *packet;
510         frescan_prio_queue_t *pqueue;
511         frescan_prio_t prio;
512         frescan_ss_t id;
513
514         packet = the_networks[chip->minor].last_packet;
515
516         id = frescan_id_get_field(packet->frame->id,
517                                   FRESCAN_FIELD_FRAG_ID);
518
519         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
520               "frame sent, minor:%u flags:0x%X frag_id:0x%X\n",
521               chip->minor, packet->flags, id);
522
523         if (packet->flags & FRESCAN_SS) {
524                 DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
525                       "calling frame_sent + program repl for id:%u\n", id);
526
527                 ret = frescan_servers_frame_sent(chip->minor, id, packet);
528                 if (ret != 0) {
529                         ERROR("could not let the server a frame was sent\n");
530                         return -1;
531                 }
532         }
533
534         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG || FRESCAN_FRAG_ENABLE_DEBUG,
535               "last packet buffer_pending_bytes=%u\n",
536               packet->buffer_pending_bytes);
537
538         if (packet->buffer_pending_bytes > 0) {
539                 if (packet->flags & FRESCAN_FP) {
540                         prio = frescan_id_get_field(packet->frame->id,
541                                         FRESCAN_FIELD_PRIO);
542
543                         DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
544                               "requeue fp packet, prio:%u\n", prio);
545
546                         pqueue = the_networks[chip->minor].queues.tx_fp_queue;
547                         ret = frescan_pqueue_requeue(pqueue, packet, prio);
548                         if (ret != 0) {
549                                 ERROR("could not requeue the packet\n");
550                                 return -1;
551                         }
552                 } else if (packet->flags & FRESCAN_SS) {
553                         DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
554                               "requeue server %u packet\n", id);
555                         ret = frescan_servers_requeue(chip->minor, id, packet);
556                         if (ret != 0) {
557                                 ERROR("could not requeue the packet\n");
558                                 return -1;
559                         }
560                 } else {
561                         ERROR("flags are not correct\n");
562                         return -1;
563                 }
564         } else {
565                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
566                       "all packet fragmets sent, freeing the packet\n");
567
568                 ret = can_framespool_free(packet->frame);
569                 if (ret != 0)  {
570                         ERROR ("could not free the frame\n");
571                         return ret;
572                 }
573
574                 ret = frescan_packets_free(packet);
575                 if (ret != 0)  {
576                         ERROR ("could not free the packet\n");
577                         return ret;
578                 }
579
580                 // TODO: signal semaphore for send_sync
581         }
582
583         the_networks[chip->minor].last_packet = NULL;
584
585         ret = frescan_hw_buffer_update(chip->minor);
586         if (ret != 0) {
587                 ERROR("could not update hw buffer\n");
588                 return -1;
589         }
590
591         return 0;
592 };
593
594 /**
595  * frescan_hook_frame_aborted - frame frame aborted hook
596  *
597  * This function will be called by the CAN driver's IRQ handler when a frame
598  * is aborted (because another frame with higher priority is waiting). We
599  * have to requeue the frame and update the buffer.
600  */
601
602 static int frescan_hook_frame_aborted(const struct can_chip_t *chip)
603 {
604         int ret;
605         frescan_packet_t *packet;
606         frescan_prio_queue_t *pqueue;
607         frescan_prio_t prio;
608         frescan_ss_t id;
609
610         packet = the_networks[chip->minor].last_packet;
611
612         id = frescan_id_get_field(packet->frame->id,
613                                   FRESCAN_FIELD_FRAG_ID);
614
615         DEBUG(FRESCAN_SENT_HOOK_ENABLE_DEBUG,
616               "frame aborted, minor:%u flags:0x%X frag_id:0x%X\n",
617               chip->minor, packet->flags, id);
618
619         if (packet->flags & FRESCAN_FP) {
620                 prio = frescan_id_get_field(packet->frame->id,
621                                             FRESCAN_FIELD_PRIO);
622
623                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
624                       "requeue fp packet, prio:%u\n", prio);
625
626                 pqueue = the_networks[chip->minor].queues.tx_fp_queue;
627                 ret = frescan_pqueue_requeue(pqueue, packet, prio);
628                 if (ret != 0) {
629                         ERROR("could not requeue the packet\n");
630                         return -1;
631                 }
632         } else if (packet->flags & FRESCAN_SS) {
633                 DEBUG(FRESCAN_FRAG_ENABLE_DEBUG,
634                       "requeue server %u packet\n", id);
635
636                 ret = frescan_servers_requeue(chip->minor, id, packet);
637                 if (ret != 0) {
638                         ERROR("could not requeue the packet\n");
639                         return -1;
640                 }
641         } else {
642                 ERROR("flags are not correct\n");
643                 return -1;
644         }
645
646         the_networks[chip->minor].last_packet = NULL;
647
648         ret = frescan_hw_buffer_update(chip->minor);
649         if (ret != 0) {
650                 ERROR("could not update hw buffer\n");
651                 return -1;
652         }
653
654         return 0;
655 }