diff options
author | Henrik Kurelid <henrik@kurelid.se> | 2008-08-24 09:20:07 -0400 |
---|---|---|
committer | Stefan Richter <stefanr@s5r6.in-berlin.de> | 2009-02-24 08:51:26 -0500 |
commit | 81c67b7f82769292a86b802590be5879413f9278 (patch) | |
tree | eebc9d27ecda8f14a48a8195e84057717fcfd89e /drivers/media | |
parent | df4846c35247a0d038c5359d502cddd59d04bc40 (diff) |
firesat: avc resend
- Add resending of AVC message to the card if no answer is received
- Replace the homebrewed event_wait function with a standard wait queue
- Clean up of log/error messages
- Increase debug level of avc communication
Signed-off-by: Henrik Kurelid <henrik@kurelid.se>
Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/dvb/firesat/avc_api.c | 173 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat.h | 1 | ||||
-rw-r--r-- | drivers/media/dvb/firesat/firesat_1394.c | 1 |
3 files changed, 95 insertions, 80 deletions
diff --git a/drivers/media/dvb/firesat/avc_api.c b/drivers/media/dvb/firesat/avc_api.c index 273c7235dd90..3c8e7e3dacc2 100644 --- a/drivers/media/dvb/firesat/avc_api.c +++ b/drivers/media/dvb/firesat/avc_api.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | static unsigned int avc_comm_debug = 0; | 27 | static unsigned int avc_comm_debug = 0; |
28 | module_param(avc_comm_debug, int, 0644); | 28 | module_param(avc_comm_debug, int, 0644); |
29 | MODULE_PARM_DESC(avc_comm_debug, "debug logging of AV/C communication, default is 0 (no)"); | 29 | MODULE_PARM_DESC(avc_comm_debug, "debug logging level [0..2] of AV/C communication, default is 0 (no)"); |
30 | 30 | ||
31 | static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal); | 31 | static int __AVCRegisterRemoteControl(struct firesat*firesat, int internal); |
32 | 32 | ||
@@ -37,22 +37,6 @@ static void avc_free_packet(struct hpsb_packet *packet) | |||
37 | hpsb_free_packet(packet); | 37 | hpsb_free_packet(packet); |
38 | } | 38 | } |
39 | 39 | ||
40 | /* | ||
41 | * Goofy routine that basically does a down_timeout function. | ||
42 | * Stolen from sbp2.c | ||
43 | */ | ||
44 | static int avc_down_timeout(atomic_t *done, int timeout) | ||
45 | { | ||
46 | int i; | ||
47 | |||
48 | for (i = timeout; (i > 0 && atomic_read(done) == 0); i-= HZ/10) { | ||
49 | set_current_state(TASK_INTERRUPTIBLE); | ||
50 | if (schedule_timeout(HZ/10)) /* 100ms */ | ||
51 | return(1); | ||
52 | } | ||
53 | return ((i > 0) ? 0:1); | ||
54 | } | ||
55 | |||
56 | static const char* get_ctype_string(__u8 ctype) | 40 | static const char* get_ctype_string(__u8 ctype) |
57 | { | 41 | { |
58 | switch(ctype) | 42 | switch(ctype) |
@@ -135,97 +119,115 @@ static void log_command_frame(const AVCCmdFrm *CmdFrm) | |||
135 | { | 119 | { |
136 | int k; | 120 | int k; |
137 | printk(KERN_INFO "AV/C Command Frame:\n"); | 121 | printk(KERN_INFO "AV/C Command Frame:\n"); |
138 | printk("CommandType=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " | 122 | printk(KERN_INFO "CommandType=%s, Address=%s(0x%02X,0x%02X), " |
139 | "length=%d\n", get_ctype_string(CmdFrm->ctype), | 123 | "opcode=%s(0x%02X), length=%d\n", |
124 | get_ctype_string(CmdFrm->ctype), | ||
140 | get_subunit_address(CmdFrm->suid, CmdFrm->sutyp), | 125 | get_subunit_address(CmdFrm->suid, CmdFrm->sutyp), |
141 | CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode), | 126 | CmdFrm->suid, CmdFrm->sutyp, get_opcode_string(CmdFrm->opcode), |
142 | CmdFrm->opcode, CmdFrm->length); | 127 | CmdFrm->opcode, CmdFrm->length); |
143 | for(k = 0; k < CmdFrm->length - 3; k++) { | 128 | if (avc_comm_debug > 1) { |
144 | if (k % 5 != 0) | 129 | for(k = 0; k < CmdFrm->length - 3; k++) { |
145 | printk(", "); | 130 | if (k % 5 != 0) |
146 | else if (k != 0) | 131 | printk(", "); |
147 | printk("\n"); | 132 | else if (k != 0) |
148 | printk("operand[%d] = %02X", k, CmdFrm->operand[k]); | 133 | printk("\n"); |
134 | printk(KERN_INFO "operand[%d] = %02X", k, | ||
135 | CmdFrm->operand[k]); | ||
136 | } | ||
137 | printk(KERN_INFO "\n"); | ||
149 | } | 138 | } |
150 | printk("\n"); | ||
151 | } | 139 | } |
152 | 140 | ||
153 | static void log_response_frame(const AVCRspFrm *RspFrm) | 141 | static void log_response_frame(const AVCRspFrm *RspFrm) |
154 | { | 142 | { |
155 | int k; | 143 | int k; |
156 | printk(KERN_INFO "AV/C Response Frame:\n"); | 144 | printk(KERN_INFO "AV/C Response Frame:\n"); |
157 | printk("Response=%s, Address=%s(0x%02X,0x%02X), opcode=%s(0x%02X), " | 145 | printk(KERN_INFO "Response=%s, Address=%s(0x%02X,0x%02X), " |
158 | "length=%d\n", get_resp_string(RspFrm->resp), | 146 | "opcode=%s(0x%02X), length=%d\n", get_resp_string(RspFrm->resp), |
159 | get_subunit_address(RspFrm->suid, RspFrm->sutyp), | 147 | get_subunit_address(RspFrm->suid, RspFrm->sutyp), |
160 | RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode), | 148 | RspFrm->suid, RspFrm->sutyp, get_opcode_string(RspFrm->opcode), |
161 | RspFrm->opcode, RspFrm->length); | 149 | RspFrm->opcode, RspFrm->length); |
162 | for(k = 0; k < RspFrm->length - 3; k++) { | 150 | if (avc_comm_debug > 1) { |
163 | if (k % 5 != 0) | 151 | for(k = 0; k < RspFrm->length - 3; k++) { |
164 | printk(", "); | 152 | if (k % 5 != 0) |
165 | else if (k != 0) | 153 | printk(KERN_INFO ", "); |
166 | printk("\n"); | 154 | else if (k != 0) |
167 | printk("operand[%d] = %02X", k, RspFrm->operand[k]); | 155 | printk(KERN_INFO "\n"); |
156 | printk(KERN_INFO "operand[%d] = %02X", k, | ||
157 | RspFrm->operand[k]); | ||
158 | } | ||
159 | printk(KERN_INFO "\n"); | ||
168 | } | 160 | } |
169 | printk("\n"); | ||
170 | } | 161 | } |
171 | 162 | ||
172 | static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, | 163 | static int __AVCWrite(struct firesat *firesat, const AVCCmdFrm *CmdFrm, |
173 | AVCRspFrm *RspFrm) { | 164 | AVCRspFrm *RspFrm) { |
174 | struct hpsb_packet *packet; | 165 | struct hpsb_packet *packet; |
175 | struct node_entry *ne; | 166 | struct node_entry *ne; |
167 | int num_tries = 0; | ||
168 | int packet_ok = 0; | ||
176 | 169 | ||
177 | ne = firesat->nodeentry; | 170 | ne = firesat->nodeentry; |
178 | if(!ne) { | 171 | if(!ne) { |
179 | printk("%s: lost node!\n",__func__); | 172 | printk(KERN_ERR "%s: lost node!\n",__func__); |
180 | return -EIO; | 173 | return -EIO; |
181 | } | 174 | } |
182 | 175 | ||
183 | /* need all input data */ | 176 | /* need all input data */ |
184 | if(!firesat || !ne || !CmdFrm) { | 177 | if(!firesat || !ne || !CmdFrm) { |
185 | printk("%s: missing input data!\n",__func__); | 178 | printk(KERN_ERR "%s: missing input data!\n",__func__); |
186 | return -EINVAL; | 179 | return -EINVAL; |
187 | } | 180 | } |
188 | 181 | ||
189 | if (avc_comm_debug == 1) { | 182 | if (avc_comm_debug > 0) { |
190 | log_command_frame(CmdFrm); | 183 | log_command_frame(CmdFrm); |
191 | } | 184 | } |
192 | 185 | ||
193 | if(RspFrm) | 186 | if(RspFrm) |
194 | atomic_set(&firesat->avc_reply_received, 0); | 187 | atomic_set(&firesat->avc_reply_received, 0); |
195 | 188 | ||
196 | packet=hpsb_make_writepacket(ne->host, ne->nodeid, | 189 | while (packet_ok == 0 && num_tries < 6) { |
197 | COMMAND_REGISTER, | 190 | num_tries++; |
198 | (quadlet_t*)CmdFrm, | 191 | packet_ok = 1; |
199 | CmdFrm->length); | 192 | packet = hpsb_make_writepacket(ne->host, ne->nodeid, |
200 | hpsb_set_packet_complete_task(packet, | 193 | COMMAND_REGISTER, |
201 | (void (*)(void*))avc_free_packet, | 194 | (quadlet_t*)CmdFrm, |
202 | packet); | 195 | CmdFrm->length); |
203 | hpsb_node_fill_packet(ne, packet); | 196 | hpsb_set_packet_complete_task(packet, |
204 | 197 | (void (*)(void*))avc_free_packet, | |
205 | if (hpsb_send_packet(packet) < 0) { | 198 | packet); |
206 | avc_free_packet(packet); | 199 | hpsb_node_fill_packet(ne, packet); |
207 | atomic_set(&firesat->avc_reply_received, 1); | 200 | |
208 | printk("%s: send failed!\n",__func__); | 201 | if (hpsb_send_packet(packet) < 0) { |
209 | return -EIO; | 202 | avc_free_packet(packet); |
210 | } | ||
211 | |||
212 | if(RspFrm) { | ||
213 | // AV/C specs say that answers should be send within | ||
214 | // 150 ms so let's time out after 200 ms | ||
215 | if(avc_down_timeout(&firesat->avc_reply_received, | ||
216 | HZ / 5)) { | ||
217 | printk("%s: timeout waiting for avc response\n", | ||
218 | __func__); | ||
219 | atomic_set(&firesat->avc_reply_received, 1); | 203 | atomic_set(&firesat->avc_reply_received, 1); |
220 | return -ETIMEDOUT; | 204 | printk(KERN_ERR "%s: send failed!\n",__func__); |
205 | return -EIO; | ||
221 | } | 206 | } |
222 | memcpy(RspFrm, firesat->respfrm, | 207 | |
223 | firesat->resp_length); | 208 | if(RspFrm) { |
224 | RspFrm->length = firesat->resp_length; | 209 | // AV/C specs say that answers should be send within |
225 | if (avc_comm_debug == 1) { | 210 | // 150 ms so let's time out after 200 ms |
226 | log_response_frame(RspFrm); | 211 | if (wait_event_timeout(firesat->avc_wait, |
212 | atomic_read(&firesat->avc_reply_received) == 1, | ||
213 | HZ / 5) == 0) { | ||
214 | packet_ok = 0; | ||
215 | } | ||
216 | else { | ||
217 | memcpy(RspFrm, firesat->respfrm, | ||
218 | firesat->resp_length); | ||
219 | RspFrm->length = firesat->resp_length; | ||
220 | if (avc_comm_debug > 0) { | ||
221 | log_response_frame(RspFrm); | ||
222 | } | ||
223 | } | ||
227 | } | 224 | } |
228 | } | 225 | } |
226 | if (packet_ok == 0) { | ||
227 | printk(KERN_ERR "%s: AV/C response timed out 6 times.\n", | ||
228 | __func__); | ||
229 | return -ETIMEDOUT; | ||
230 | } | ||
229 | 231 | ||
230 | return 0; | 232 | return 0; |
231 | } | 233 | } |
@@ -292,7 +294,8 @@ int AVCRecv(struct firesat *firesat, u8 *data, size_t length) { | |||
292 | } | 294 | } |
293 | #endif | 295 | #endif |
294 | if(atomic_read(&firesat->avc_reply_received) == 1) { | 296 | if(atomic_read(&firesat->avc_reply_received) == 1) { |
295 | printk("%s: received out-of-order AVC response, ignored\n",__func__); | 297 | printk(KERN_ERR "%s: received out-of-order AVC response, " |
298 | "ignored\n",__func__); | ||
296 | return -EINVAL; | 299 | return -EINVAL; |
297 | } | 300 | } |
298 | // AVCRspFrm *resp=(AVCRspFrm *)data; | 301 | // AVCRspFrm *resp=(AVCRspFrm *)data; |
@@ -312,6 +315,7 @@ int AVCRecv(struct firesat *firesat, u8 *data, size_t length) { | |||
312 | firesat->resp_length=length; | 315 | firesat->resp_length=length; |
313 | 316 | ||
314 | atomic_set(&firesat->avc_reply_received, 1); | 317 | atomic_set(&firesat->avc_reply_received, 1); |
318 | wake_up(&firesat->avc_wait); | ||
315 | 319 | ||
316 | return 0; | 320 | return 0; |
317 | } | 321 | } |
@@ -740,11 +744,12 @@ int AVCIdentifySubunit(struct firesat *firesat, unsigned char *systemId, int *tr | |||
740 | return -EIO; | 744 | return -EIO; |
741 | 745 | ||
742 | if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { | 746 | if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { |
743 | printk("%s: AVCWrite returned error code %d\n",__func__,RspFrm.resp); | 747 | printk(KERN_ERR "%s: AVCWrite returned error code %d\n", |
748 | __func__, RspFrm.resp); | ||
744 | return -EINVAL; | 749 | return -EINVAL; |
745 | } | 750 | } |
746 | if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) { | 751 | if(((RspFrm.operand[3] << 8) + RspFrm.operand[4]) != 8) { |
747 | printk("%s: Invalid response length\n",__func__); | 752 | printk(KERN_ERR "%s: Invalid response length\n", __func__); |
748 | return -EINVAL; | 753 | return -EINVAL; |
749 | } | 754 | } |
750 | if(systemId) | 755 | if(systemId) |
@@ -777,7 +782,8 @@ int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_in | |||
777 | return -EIO; | 782 | return -EIO; |
778 | 783 | ||
779 | if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { | 784 | if(RspFrm.resp != STABLE && RspFrm.resp != ACCEPTED) { |
780 | printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); | 785 | printk(KERN_ERR "%s: AVCWrite returned code %d\n", |
786 | __func__, RspFrm.resp); | ||
781 | return -EINVAL; | 787 | return -EINVAL; |
782 | } | 788 | } |
783 | 789 | ||
@@ -788,7 +794,8 @@ int AVCTunerStatus(struct firesat *firesat, ANTENNA_INPUT_INFO *antenna_input_in | |||
788 | sizeof(ANTENNA_INPUT_INFO)); | 794 | sizeof(ANTENNA_INPUT_INFO)); |
789 | return 0; | 795 | return 0; |
790 | } | 796 | } |
791 | printk("%s: invalid info returned from AVC\n",__func__); | 797 | printk(KERN_ERR "%s: invalid tuner status (op=%d,length=%d) returned " |
798 | "from AVC\n", __func__, RspFrm.operand[1], length); | ||
792 | return -EINVAL; | 799 | return -EINVAL; |
793 | } | 800 | } |
794 | 801 | ||
@@ -800,7 +807,8 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst, | |||
800 | AVCRspFrm RspFrm; | 807 | AVCRspFrm RspFrm; |
801 | int i,j; | 808 | int i,j; |
802 | 809 | ||
803 | printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n",__func__,voltage,burst,conttone); | 810 | printk(KERN_INFO "%s: voltage = %x, burst = %x, conttone = %x\n", |
811 | __func__, voltage, burst, conttone); | ||
804 | 812 | ||
805 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); | 813 | memset(&CmdFrm, 0, sizeof(AVCCmdFrm)); |
806 | 814 | ||
@@ -822,11 +830,13 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst, | |||
822 | 830 | ||
823 | for(j=0;j<nrdiseq;j++) { | 831 | for(j=0;j<nrdiseq;j++) { |
824 | int k; | 832 | int k; |
825 | printk(KERN_INFO "%s: diseq %d len %x\n",__func__,j,diseqcmd[j].msg_len); | 833 | printk(KERN_INFO "%s: diseq %d len %x\n", |
834 | __func__, j, diseqcmd[j].msg_len); | ||
826 | CmdFrm.operand[i++]=diseqcmd[j].msg_len; | 835 | CmdFrm.operand[i++]=diseqcmd[j].msg_len; |
827 | 836 | ||
828 | for(k=0;k<diseqcmd[j].msg_len;k++) { | 837 | for(k=0;k<diseqcmd[j].msg_len;k++) { |
829 | printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n",__func__,j,k,diseqcmd[j].msg[k]); | 838 | printk(KERN_INFO "%s: diseq %d msg[%d] = %x\n", |
839 | __func__, j, k, diseqcmd[j].msg[k]); | ||
830 | CmdFrm.operand[i++]=diseqcmd[j].msg[k]; | 840 | CmdFrm.operand[i++]=diseqcmd[j].msg[k]; |
831 | } | 841 | } |
832 | } | 842 | } |
@@ -847,7 +857,8 @@ int AVCLNBControl(struct firesat *firesat, char voltage, char burst, | |||
847 | return -EIO; | 857 | return -EIO; |
848 | 858 | ||
849 | if(RspFrm.resp != ACCEPTED) { | 859 | if(RspFrm.resp != ACCEPTED) { |
850 | printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); | 860 | printk(KERN_ERR "%s: AVCWrite returned code %d\n", |
861 | __func__, RspFrm.resp); | ||
851 | return -EINVAL; | 862 | return -EINVAL; |
852 | } | 863 | } |
853 | 864 | ||
@@ -879,7 +890,8 @@ int AVCSubUnitInfo(struct firesat *firesat, char *subunitcount) | |||
879 | return -EIO; | 890 | return -EIO; |
880 | 891 | ||
881 | if(RspFrm.resp != STABLE) { | 892 | if(RspFrm.resp != STABLE) { |
882 | printk("%s: AVCWrite returned code %d\n",__func__,RspFrm.resp); | 893 | printk(KERN_ERR "%s: AVCWrite returned code %d\n", |
894 | __func__, RspFrm.resp); | ||
883 | return -EINVAL; | 895 | return -EINVAL; |
884 | } | 896 | } |
885 | 897 | ||
@@ -1100,9 +1112,10 @@ int avc_ca_pmt(struct firesat *firesat, char *msg, int length) | |||
1100 | CmdFrm.opcode = VENDOR; | 1112 | CmdFrm.opcode = VENDOR; |
1101 | 1113 | ||
1102 | if (msg[0] != LIST_MANAGEMENT_ONLY) { | 1114 | if (msg[0] != LIST_MANAGEMENT_ONLY) { |
1103 | printk(KERN_ERR "The only list_manasgement parameter that is " | 1115 | printk(KERN_INFO "%s: list_management %d not support. " |
1104 | "supported by the firesat driver is \"only\" (3)."); | 1116 | "Forcing list_management to \"only\" (3). \n", |
1105 | return -EFAULT; | 1117 | __func__, msg[0]); |
1118 | msg[0] = LIST_MANAGEMENT_ONLY; | ||
1106 | } | 1119 | } |
1107 | // We take the cmd_id from the programme level only! | 1120 | // We take the cmd_id from the programme level only! |
1108 | list_management = msg[0]; | 1121 | list_management = msg[0]; |
diff --git a/drivers/media/dvb/firesat/firesat.h b/drivers/media/dvb/firesat/firesat.h index 1beed177d98b..f0bac244783a 100644 --- a/drivers/media/dvb/firesat/firesat.h +++ b/drivers/media/dvb/firesat/firesat.h | |||
@@ -140,6 +140,7 @@ struct firesat { | |||
140 | int ca_time_interval; | 140 | int ca_time_interval; |
141 | 141 | ||
142 | struct semaphore avc_sem; | 142 | struct semaphore avc_sem; |
143 | wait_queue_head_t avc_wait; | ||
143 | atomic_t avc_reply_received; | 144 | atomic_t avc_reply_received; |
144 | 145 | ||
145 | atomic_t reschedule_remotecontrol; | 146 | atomic_t reschedule_remotecontrol; |
diff --git a/drivers/media/dvb/firesat/firesat_1394.c b/drivers/media/dvb/firesat/firesat_1394.c index 04ad31666fb9..b19e59416b59 100644 --- a/drivers/media/dvb/firesat/firesat_1394.c +++ b/drivers/media/dvb/firesat/firesat_1394.c | |||
@@ -208,6 +208,7 @@ static int firesat_probe(struct device *dev) | |||
208 | } | 208 | } |
209 | 209 | ||
210 | sema_init(&firesat->avc_sem, 1); | 210 | sema_init(&firesat->avc_sem, 1); |
211 | init_waitqueue_head(&firesat->avc_wait); | ||
211 | atomic_set(&firesat->avc_reply_received, 1); | 212 | atomic_set(&firesat->avc_reply_received, 1); |
212 | sema_init(&firesat->demux_sem, 1); | 213 | sema_init(&firesat->demux_sem, 1); |
213 | atomic_set(&firesat->reschedule_remotecontrol, 0); | 214 | atomic_set(&firesat->reschedule_remotecontrol, 0); |