en50221_stdcam_hlci.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. en50221 encoder An implementation for libdvb
  3. an implementation for the en50221 transport layer
  4. Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU Lesser General Public License as
  7. published by the Free Software Foundation; either version 2.1 of
  8. the License, or (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 Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. */
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <limits.h>
  20. #include <string.h>
  21. #include <errno.h>
  22. #include <libdvbapi/dvbca.h>
  23. #include "en50221_app_utils.h"
  24. #include "en50221_app_tags.h"
  25. #include "en50221_stdcam.h"
  26. struct en50221_stdcam_hlci {
  27. struct en50221_stdcam stdcam;
  28. int cafd;
  29. int slotnum;
  30. int initialised;
  31. struct en50221_app_send_functions sendfuncs;
  32. };
  33. static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd);
  34. static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam);
  35. static int hlci_cam_added(struct en50221_stdcam_hlci *hlci);
  36. static int hlci_send_data(void *arg, uint16_t session_number,
  37. uint8_t * data, uint16_t data_length);
  38. static int hlci_send_datav(void *arg, uint16_t session_number,
  39. struct iovec *vector, int iov_count);
  40. struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum)
  41. {
  42. // try and allocate space for the HLCI stdcam
  43. struct en50221_stdcam_hlci *hlci =
  44. malloc(sizeof(struct en50221_stdcam_hlci));
  45. if (hlci == NULL) {
  46. return NULL;
  47. }
  48. memset(hlci, 0, sizeof(struct en50221_stdcam_hlci));
  49. // create the sendfuncs
  50. hlci->sendfuncs.arg = hlci;
  51. hlci->sendfuncs.send_data = hlci_send_data;
  52. hlci->sendfuncs.send_datav = hlci_send_datav;
  53. // create the resources (NOTE: we just use fake session numbers here)
  54. hlci->stdcam.ai_resource = en50221_app_ai_create(&hlci->sendfuncs);
  55. hlci->stdcam.ai_session_number = 0;
  56. hlci->stdcam.ca_resource = en50221_app_ca_create(&hlci->sendfuncs);
  57. hlci->stdcam.ca_session_number = 1;
  58. // hlci->stdcam.mmi_resource = en50221_app_mmi_create(&hlci->sendfuncs);
  59. hlci->stdcam.mmi_session_number = -1;
  60. // done
  61. hlci->stdcam.destroy = en50221_stdcam_hlci_destroy;
  62. hlci->stdcam.poll = en50221_stdcam_hlci_poll;
  63. hlci->slotnum = slotnum;
  64. hlci->cafd = cafd;
  65. return &hlci->stdcam;
  66. }
  67. static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd)
  68. {
  69. struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
  70. if (hlci->stdcam.ai_resource)
  71. en50221_app_ai_destroy(hlci->stdcam.ai_resource);
  72. if (hlci->stdcam.ca_resource)
  73. en50221_app_ca_destroy(hlci->stdcam.ca_resource);
  74. if (hlci->stdcam.mmi_resource)
  75. en50221_app_mmi_destroy(hlci->stdcam.mmi_resource);
  76. if (closefd)
  77. close(hlci->cafd);
  78. free(hlci);
  79. }
  80. static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam)
  81. {
  82. struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
  83. switch(dvbca_get_cam_state(hlci->cafd, hlci->slotnum)) {
  84. case DVBCA_CAMSTATE_MISSING:
  85. hlci->initialised = 0;
  86. break;
  87. case DVBCA_CAMSTATE_READY:
  88. case DVBCA_CAMSTATE_INITIALISING:
  89. if (!hlci->initialised)
  90. hlci_cam_added(hlci);
  91. break;
  92. }
  93. // delay to prevent busy loop
  94. usleep(10);
  95. if (!hlci->initialised) {
  96. return EN50221_STDCAM_CAM_NONE;
  97. }
  98. return EN50221_STDCAM_CAM_OK;
  99. }
  100. static int hlci_cam_added(struct en50221_stdcam_hlci *hlci)
  101. {
  102. uint8_t buf[256];
  103. int size;
  104. // get application information
  105. if (en50221_app_ai_enquiry(hlci->stdcam.ai_resource, 0)) {
  106. return -EIO;
  107. }
  108. if ((size = dvbca_hlci_read(hlci->cafd, TAG_APP_INFO, buf, sizeof(buf))) < 0) {
  109. return size;
  110. }
  111. if (en50221_app_ai_message(hlci->stdcam.ai_resource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) {
  112. return -EIO;
  113. }
  114. // we forge a fake CA_INFO here so the main app works - since it will expect a CA_INFO
  115. // this will be replaced with a proper call (below) when the driver support is there
  116. buf[0] = TAG_CA_INFO >> 16;
  117. buf[1] = (uint8_t) (TAG_CA_INFO >> 8);
  118. buf[2] = (uint8_t) TAG_CA_INFO;
  119. buf[3] = 0;
  120. if (en50221_app_ca_message(hlci->stdcam.ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) {
  121. return -EIO;
  122. }
  123. /*
  124. // get CA information
  125. if (en50221_app_ca_info_enq(ca_resource, 0)) {
  126. fprintf(stderr, "Failed to send CA INFO enquiry\n");
  127. cafd = -1;
  128. return -1;
  129. }
  130. if ((size = dvbca_hlci_read(cafd, TAG_CA_INFO, buf, sizeof(buf))) < 0) {
  131. fprintf(stderr, "Failed to read CA INFO\n");
  132. cafd = -1;
  133. return -1;
  134. }
  135. if (en50221_app_ca_message(ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, size)) {
  136. fprintf(stderr, "Failed to parse CA INFO\n");
  137. cafd = -1;
  138. return -1;
  139. }
  140. */
  141. // done
  142. hlci->initialised = 1;
  143. return 0;
  144. }
  145. static int hlci_send_data(void *arg, uint16_t session_number,
  146. uint8_t * data, uint16_t data_length)
  147. {
  148. (void) session_number;
  149. struct en50221_stdcam_hlci *hlci = arg;
  150. return dvbca_hlci_write(hlci->cafd, data, data_length);
  151. }
  152. static int hlci_send_datav(void *arg, uint16_t session_number,
  153. struct iovec *vector, int iov_count)
  154. {
  155. (void) session_number;
  156. struct en50221_stdcam_hlci *hlci = arg;
  157. // calculate the total length of the data to send
  158. uint32_t data_size = 0;
  159. int i;
  160. for (i = 0; i < iov_count; i++) {
  161. data_size += vector[i].iov_len;
  162. }
  163. // allocate memory for it
  164. uint8_t *buf = malloc(data_size);
  165. if (buf == NULL) {
  166. return -1;
  167. }
  168. // merge the iovecs
  169. uint32_t pos = 0;
  170. for (i = 0; i < iov_count; i++) {
  171. memcpy(buf + pos, vector[i].iov_base, vector[i].iov_len);
  172. pos += vector[i].iov_len;
  173. }
  174. // sendit and cleanup
  175. int status = dvbca_hlci_write(hlci->cafd, buf, data_size);
  176. free(buf);
  177. return status;
  178. }