aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/isdn/i4l/isdn_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/isdn/i4l/isdn_common.c')
-rw-r--r--drivers/isdn/i4l/isdn_common.c112
1 files changed, 112 insertions, 0 deletions
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c
index 4643df097bfe..22759c01746a 100644
--- a/drivers/isdn/i4l/isdn_common.c
+++ b/drivers/isdn/i4l/isdn_common.c
@@ -857,6 +857,118 @@ isdn_readbchan(int di, int channel, u_char * buf, u_char * fp, int len, wait_que
857 return count; 857 return count;
858} 858}
859 859
860/*
861 * isdn_readbchan_tty() tries to get data from the read-queue.
862 * It MUST be called with interrupts off.
863 *
864 * Be aware that this is not an atomic operation when sleep != 0, even though
865 * interrupts are turned off! Well, like that we are currently only called
866 * on behalf of a read system call on raw device files (which are documented
867 * to be dangerous and for for debugging purpose only). The inode semaphore
868 * takes care that this is not called for the same minor device number while
869 * we are sleeping, but access is not serialized against simultaneous read()
870 * from the corresponding ttyI device. Can other ugly events, like changes
871 * of the mapping (di,ch)<->minor, happen during the sleep? --he
872 */
873int
874isdn_readbchan_tty(int di, int channel, struct tty_struct *tty, int cisco_hack)
875{
876 int count;
877 int count_pull;
878 int count_put;
879 int dflag;
880 struct sk_buff *skb;
881 char last = 0;
882 int len;
883
884 if (!dev->drv[di])
885 return 0;
886 if (skb_queue_empty(&dev->drv[di]->rpqueue[channel]))
887 return 0;
888
889 len = tty_buffer_request_room(tty, dev->drv[di]->rcvcount[channel]);
890 if(len == 0)
891 return len;
892
893 count = 0;
894 while (len) {
895 if (!(skb = skb_peek(&dev->drv[di]->rpqueue[channel])))
896 break;
897#ifdef CONFIG_ISDN_AUDIO
898 if (ISDN_AUDIO_SKB_LOCK(skb))
899 break;
900 ISDN_AUDIO_SKB_LOCK(skb) = 1;
901 if ((ISDN_AUDIO_SKB_DLECOUNT(skb)) || (dev->drv[di]->DLEflag & (1 << channel))) {
902 char *p = skb->data;
903 unsigned long DLEmask = (1 << channel);
904
905 dflag = 0;
906 count_pull = count_put = 0;
907 while ((count_pull < skb->len) && (len > 0)) {
908 len--;
909 if (dev->drv[di]->DLEflag & DLEmask) {
910 last = DLE;
911 dev->drv[di]->DLEflag &= ~DLEmask;
912 } else {
913 last = *p;
914 if (last == DLE) {
915 dev->drv[di]->DLEflag |= DLEmask;
916 (ISDN_AUDIO_SKB_DLECOUNT(skb))--;
917 }
918 p++;
919 count_pull++;
920 }
921 count_put++;
922 }
923 if (count_pull >= skb->len)
924 dflag = 1;
925 } else {
926#endif
927 /* No DLE's in buff, so simply copy it */
928 dflag = 1;
929 if ((count_pull = skb->len) > len) {
930 count_pull = len;
931 dflag = 0;
932 }
933 count_put = count_pull;
934 if(count_put > 1)
935 tty_insert_flip_string(tty, skb->data, count_put - 1);
936 last = skb->data[count_put] - 1;
937 len -= count_put;
938#ifdef CONFIG_ISDN_AUDIO
939 }
940#endif
941 count += count_put;
942 if (dflag) {
943 /* We got all the data in this buff.
944 * Now we can dequeue it.
945 */
946 if(cisco_hack)
947 tty_insert_flip_char(tty, last, 0xFF);
948 else
949 tty_insert_flip_char(tty, last, TTY_NORMAL);
950#ifdef CONFIG_ISDN_AUDIO
951 ISDN_AUDIO_SKB_LOCK(skb) = 0;
952#endif
953 skb = skb_dequeue(&dev->drv[di]->rpqueue[channel]);
954 dev_kfree_skb(skb);
955 } else {
956 tty_insert_flip_char(tty, last, TTY_NORMAL);
957 /* Not yet emptied this buff, so it
958 * must stay in the queue, for further calls
959 * but we pull off the data we got until now.
960 */
961 skb_pull(skb, count_pull);
962#ifdef CONFIG_ISDN_AUDIO
963 ISDN_AUDIO_SKB_LOCK(skb) = 0;
964#endif
965 }
966 dev->drv[di]->rcvcount[channel] -= count_put;
967 }
968 return count;
969}
970
971
860static __inline int 972static __inline int
861isdn_minor2drv(int minor) 973isdn_minor2drv(int minor)
862{ 974{